rank.c File Reference

#include <stdio.h>
#include <assert.h>
#include "binding.h"
#include "comb.h"
#include "db.h"
#include "defines.h"
#include "expr.h"
#include "fsm.h"
#include "func_iter.h"
#include "func_unit.h"
#include "link.h"
#include "profiler.h"
#include "rank.h"
#include "report.h"
#include "util.h"
#include "vector.h"
#include "vsignal.h"

Functions

comp_cdd_covrank_create_comp_cdd_cov (const char *cdd_name, bool required, uint64 timesteps)
void rank_dealloc_comp_cdd_cov (comp_cdd_cov *comp_cov)
static void rank_usage ()
static bool rank_parse_args (int argc, int last_arg, const char **argv)
static void rank_check_index (unsigned type, uint64 index, int line)
static void rank_gather_signal_cov (vsignal *sig, comp_cdd_cov *comp_cov)
static void rank_gather_comb_cov (expression *exp, comp_cdd_cov *comp_cov)
static void rank_gather_expression_cov (expression *exp, unsigned int exclude, comp_cdd_cov *comp_cov)
static void rank_gather_fsm_cov (fsm_table *table, comp_cdd_cov *comp_cov)
static void rank_calc_num_cps (funit_inst *inst, uint64 nums[CP_TYPE_NUM])
static void rank_gather_comp_cdd_cov (funit_inst *inst, comp_cdd_cov *comp_cov)
static void rank_read_cdd (const char *cdd_name, bool required, bool first, comp_cdd_cov ***comp_cdds, unsigned int *comp_cdd_num)
static void rank_selected_cdd_cov (comp_cdd_cov **comp_cdds, unsigned int comp_cdd_num, uint16 *ranked_merged, uint16 *unranked_merged, unsigned int next_cdd, unsigned int selected_cdd)
static void rank_perform_weighted_selection (comp_cdd_cov **comp_cdds, unsigned int comp_cdd_num, uint16 *ranked_merged, uint16 *unranked_merged, unsigned int next_cdd, unsigned int *cdds_ranked)
static void rank_perform_greedy_sort (comp_cdd_cov **comp_cdds, unsigned int comp_cdd_num, uint16 *ranked_merged, uint64 num_ranked)
uint64 rank_count_cps (uint16 *list, unsigned int list_size)
static void rank_perform (comp_cdd_cov **comp_cdds, unsigned int comp_cdd_num)
static void rank_output (comp_cdd_cov **comp_cdds, unsigned int comp_cdd_num)
void command_rank (int argc, int last_arg, const char **argv)
 Parses command-line for rank options and performs rank command.

Variables

char user_msg [USER_MSG_LENGTH]
const exp_info exp_op_info [EXP_OP_NUM]
db ** db_list
uint64 num_timesteps
bool quiet_mode
bool terse_mode
bool debug_mode
int64 largest_malloc_size
bool report_line
bool report_toggle
bool report_combination
bool report_fsm
bool report_assertion
bool report_memory
bool allow_multi_expr
static str_linkrank_in_head = NULL
static str_linkrank_in_tail = NULL
static char * rank_file = NULL
static uint64 num_cps [CP_TYPE_NUM] = {0}
static unsigned int cdd_type_weight [CP_TYPE_NUM] = {1,1,1,1,1,0}
static bool cdd_type_set [CP_TYPE_NUM] = {0}
static bool flag_names_only = FALSE
static unsigned int cp_depth = 0
static unsigned int longest_name_len = 0
static bool rank_verbose = FALSE

Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
6/28/2008

Function Documentation

void command_rank ( int  argc,
int  last_arg,
const char **  argv 
)

Parses command-line for rank options and performs rank command.

Performs merge command functionality.

Parameters:
argc Number of arguments in command-line to parse
last_arg Index of last parsed argument from list
argv List of arguments from command-line to parse

References allow_multi_expr, Catch_anonymous, COVERED_HEADER, FALSE, free_safe, HEADER, largest_malloc_size, str_link_s::next, NORMAL, print_output(), PROFILE, PROFILE_END, rank_dealloc_comp_cdd_cov(), rank_file, rank_output(), rank_parse_args(), rank_perform(), rank_read_cdd(), rank_verbose, report_assertion, report_combination, report_fsm, report_line, report_memory, report_toggle, str_link_s::str, str_link_delete_list(), str_link_s::suppl, Throw, TRUE, Try, user_msg, and USER_MSG_LENGTH.

Referenced by main().

01733   { PROFILE(COMMAND_RANK);
01734 
01735   int            i, j;
01736   unsigned int   rv;
01737   comp_cdd_cov** comp_cdds    = NULL;
01738   unsigned int   comp_cdd_num = 0;
01739   bool           error        = FALSE;
01740 
01741   /* Output header information */
01742   rv = snprintf( user_msg, USER_MSG_LENGTH, COVERED_HEADER );
01743   assert( rv < USER_MSG_LENGTH );
01744   print_output( user_msg, HEADER, __FILE__, __LINE__ );
01745 
01746   Try {
01747 
01748     unsigned int rv;
01749     bool         first  = TRUE;
01750     str_link*    strl;
01751     timer*       atimer = NULL;
01752 
01753     /* Parse score command-line */
01754     if( !rank_parse_args( argc, last_arg, argv ) ) {
01755 
01756       /* Make sure that all coverage points are accumulated */
01757       report_line        = TRUE;
01758       report_toggle      = TRUE;
01759       report_combination = TRUE;
01760       report_fsm         = TRUE;
01761       report_assertion   = TRUE;
01762       report_memory      = TRUE;
01763       allow_multi_expr   = FALSE;
01764 
01765       /* Start timer */
01766       if( rank_verbose ) {
01767         timer_clear( &atimer );
01768         timer_start( &atimer );
01769       }
01770 
01771       /* Read in databases to merge */
01772       strl = rank_in_head;
01773       while( strl != NULL ) {
01774         rv = snprintf( user_msg, USER_MSG_LENGTH, "Reading CDD file \"%s\"", strl->str );
01775         assert( rv < USER_MSG_LENGTH );
01776         print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01777         rv = fflush( stdout );
01778         assert( rv == 0 );
01779         rank_read_cdd( strl->str, (strl->suppl == 1), first, &comp_cdds, &comp_cdd_num );
01780         first = FALSE;
01781         strl  = strl->next;
01782       }
01783 
01784       if( rank_verbose ) {
01785         timer_stop( &atimer );
01786         rv = snprintf( user_msg, USER_MSG_LENGTH, "Completed reading in CDD files in %s", timer_to_string( atimer ) );
01787         assert( rv < USER_MSG_LENGTH );
01788         print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01789         free_safe( atimer, sizeof( timer ) );
01790       }
01791 
01792       /* Peaform the ranking algorithm */
01793       rank_perform( comp_cdds, comp_cdd_num );
01794 
01795       /* Output the results */
01796       rank_output( comp_cdds, comp_cdd_num );
01797 
01798       /*@-duplicatequals -formatcode -formattype@*/
01799       rv = snprintf( user_msg, USER_MSG_LENGTH, "Dynamic memory allocated:   %" FMT64 "u bytes", largest_malloc_size );
01800       assert( rv < USER_MSG_LENGTH );
01801       /*@=duplicatequals =formatcode =formattype@*/
01802       print_output( "", NORMAL, __FILE__, __LINE__ );
01803       print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01804       print_output( "", NORMAL, __FILE__, __LINE__ );
01805 
01806     }
01807 
01808   } Catch_anonymous {
01809     error = TRUE;
01810   }
01811 
01812   /* Deallocate other allocated variables */
01813   str_link_delete_list( rank_in_head );
01814 
01815   /* Deallocate the compressed CDD coverage structures */
01816   for( i=0; i<comp_cdd_num; i++ ) {
01817     rank_dealloc_comp_cdd_cov( comp_cdds[i] );
01818   }
01819   free_safe( comp_cdds, (sizeof( comp_cdd_cov* ) * comp_cdd_num) );
01820 
01821   free_safe( rank_file, (strlen( rank_file ) + 1) );
01822 
01823   if( error ) {
01824     Throw 0;
01825   }
01826 
01827   PROFILE_END;
01828 
01829 }

static void rank_calc_num_cps ( funit_inst inst,
uint64  nums[CP_TYPE_NUM] 
) [static]

Recursively iterates through the instance tree, accumulating values for num_cps array.

Parameters:
inst Pointer to instance tree to calculate num_cps array
nums Array of coverage point numbers to populate

References statistic_s::arc_total, statistic_s::assert_total, funit_inst_s::child_head, statistic_s::comb_total, CP_TYPE_ASSERT, CP_TYPE_FSM, CP_TYPE_LINE, CP_TYPE_LOGIC, CP_TYPE_MEM, CP_TYPE_TOGGLE, statistic_s::line_total, statistic_s::mem_ae_total, statistic_s::mem_tog_total, funit_inst_s::next, PROFILE, PROFILE_END, funit_inst_s::stat, statistic_s::state_total, and statistic_s::tog_total.

Referenced by rank_read_cdd().

00973   { PROFILE(RANK_CALC_NUM_CPS);
00974 
00975   funit_inst* child;  /* Pointer to child instance */
00976 
00977   /* Iterate through children instances */
00978   child = inst->child_head;
00979   while( child != NULL ) {
00980     rank_calc_num_cps( child, nums );
00981     child = child->next;
00982   }
00983 
00984   /* Add totals to global num_cps array */
00985   nums[CP_TYPE_LINE]   += inst->stat->line_total;
00986   nums[CP_TYPE_TOGGLE] += (inst->stat->tog_total * 2);
00987   nums[CP_TYPE_MEM]    += (inst->stat->mem_ae_total * 2) + (inst->stat->mem_tog_total * 2);
00988   nums[CP_TYPE_LOGIC]  += inst->stat->comb_total;
00989   if( inst->stat->state_total > 0 ) {
00990     nums[CP_TYPE_FSM] += (unsigned int)inst->stat->state_total;
00991   }
00992   if( inst->stat->arc_total > 0 ) {
00993     nums[CP_TYPE_FSM] += (unsigned int)inst->stat->arc_total;
00994   }
00995   nums[CP_TYPE_ASSERT] += inst->stat->assert_total;
00996 
00997   PROFILE_END;
00998 
00999 }

static void rank_check_index ( unsigned  type,
uint64  index,
int  line 
) [static]

Checks to make sure that index that will be used exceeds the maximum index (to eliminate memory overruns). Throws exception if the index that will be used violates this check.

Parameters:
type Type of index that is being checked
index Index value to check
line Line number in source code that hit this error

References FATAL, num_cps, print_output(), PROFILE, PROFILE_END, Throw, user_msg, and USER_MSG_LENGTH.

Referenced by rank_gather_comb_cov(), rank_gather_expression_cov(), rank_gather_fsm_cov(), and rank_gather_signal_cov().

00671   { PROFILE(RANK_CHECK_INDEX);
00672 
00673   if( index >= num_cps[type] ) {
00674     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Last read in CDD file is incompatible with previously read in CDD files.  Exiting..." );
00675     assert( rv < USER_MSG_LENGTH );
00676     print_output( user_msg, FATAL, __FILE__, line );
00677     Throw 0;
00678   }
00679 
00680   PROFILE_END;
00681 
00682 }

uint64 rank_count_cps ( uint16 *  list,
unsigned int  list_size 
)
Returns:
Returns the number of coverage points hit in the given list.
Parameters:
list List of cp counts
list_size Number of elements in the list

References PROFILE, and PROFILE_END.

Referenced by rank_perform().

01338   { PROFILE(RANK_COUNT_CPS);
01339 
01340   uint64       cps = 0;
01341   unsigned int i;
01342 
01343   for( i=0; i<list_size; i++ ) {
01344     cps += (list[i] > 0) ? 1 : 0;
01345   }
01346 
01347   PROFILE_END;
01348 
01349   return( cps );
01350 
01351 }

comp_cdd_cov* rank_create_comp_cdd_cov ( const char *  cdd_name,
bool  required,
uint64  timesteps 
)
Returns:
Returns a pointer to a newly allocated and initialized compressed CDD coverage structure.
Parameters:
cdd_name Name of CDD file that this structure was created from
required Set to TRUE if this CDD is required to be ranked by the user
timesteps Number of simulation timesteps that occurred in the CDD

References calloc_safe, comp_cdd_cov_s::cdd_name, CP_TYPE_NUM, comp_cdd_cov_s::cps, comp_cdd_cov_s::cps_index, longest_name_len, malloc_safe, num_cps, PROFILE, PROFILE_END, comp_cdd_cov_s::required, strdup_safe, comp_cdd_cov_s::timesteps, comp_cdd_cov_s::total_cps, UL_DIV, and comp_cdd_cov_s::unique_cps.

Referenced by rank_read_cdd().

00173   { PROFILE(RANK_CREATE_COMP_CDD_COV);
00174 
00175   comp_cdd_cov* comp_cov;
00176   unsigned int  i;
00177 
00178   /* Allocate and initialize */
00179   comp_cov             = (comp_cdd_cov*)malloc_safe( sizeof( comp_cdd_cov ) );
00180   comp_cov->cdd_name   = strdup_safe( cdd_name );
00181   comp_cov->timesteps  = timesteps;
00182   comp_cov->total_cps  = 0;
00183   comp_cov->unique_cps = 0;
00184   comp_cov->required   = required;
00185 
00186   /* Save longest name length */
00187   if( strlen( comp_cov->cdd_name ) > longest_name_len ) {
00188     longest_name_len = strlen( comp_cov->cdd_name );
00189   }
00190 
00191   for( i=0; i<CP_TYPE_NUM; i++ ) {
00192     comp_cov->cps_index[i] = 0;
00193     if( num_cps[i] > 0 ) {
00194       comp_cov->cps[i] = (ulong*)calloc_safe( (UL_DIV(num_cps[i]) + 1), sizeof( ulong ) );
00195     } else {
00196       comp_cov->cps[i] = NULL;
00197     }
00198   }
00199 
00200   PROFILE_END;
00201 
00202   return( comp_cov );
00203 
00204 }

void rank_dealloc_comp_cdd_cov ( comp_cdd_cov comp_cov  ) 

Deallocates the specified compressed CDD coverage structure.

Parameters:
comp_cov Pointer to compressed CDD coverage structure to deallocate

References comp_cdd_cov_s::cdd_name, CP_TYPE_NUM, comp_cdd_cov_s::cps, free_safe, num_cps, PROFILE, PROFILE_END, and UL_DIV.

Referenced by command_rank(), and rank_read_cdd().

00211   { PROFILE(RANK_DEALLOC_COMP_CDD_COV);
00212 
00213   if( comp_cov != NULL ) {
00214 
00215     unsigned int i;
00216 
00217     /* Deallocate name */
00218     free_safe( comp_cov->cdd_name, (strlen( comp_cov->cdd_name ) + 1) );
00219 
00220     /* Deallocate compressed coverage point information */
00221     for( i=0; i<CP_TYPE_NUM; i++ ) {
00222       free_safe( comp_cov->cps[i], (sizeof( ulong ) * (UL_DIV( num_cps[i] ) + 1)) );
00223     }
00224 
00225     /* Now deallocate ourselves */
00226     free_safe( comp_cov, sizeof( comp_cdd_cov ) );
00227 
00228   }
00229 
00230   PROFILE_END;
00231 
00232 }

static void rank_gather_comb_cov ( expression exp,
comp_cdd_cov comp_cov 
) [static]

Recursively iterates through the given expression tree, gathering all combinational logic coverage information and populating the given compressed CDD coverage structure accordingly.

Parameters:
exp Pointer to current expression to gather combinational logic coverage from
comp_cov Pointer to compressed CDD coverage structure to populate

References AND_COMB, esuppl_u::comb_cntd, CP_TYPE_LOGIC, comp_cdd_cov_s::cps, comp_cdd_cov_s::cps_index, 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, EXPR_IS_COMB, EXPR_IS_EVENT, EXPR_IS_MEASURABLE, expression_is_static_only(), exp_info_s::is_comb, expression_s::left, expression_s::op, OR_COMB, esuppl_u::part, PROFILE, PROFILE_END, rank_check_index(), expression_s::right, exp_info_s::suppl, expression_s::suppl, UL_DIV, and UL_MOD.

Referenced by rank_gather_expression_cov().

00803   { PROFILE(RANK_GATHER_COMB_COV);
00804 
00805   if( exp != NULL ) {
00806 
00807     /* Gather combination coverage information from children */
00808     rank_gather_comb_cov( exp->left,  comp_cov );
00809     rank_gather_comb_cov( exp->right, comp_cov );
00810 
00811     /* Calculate combinational logic coverage information */
00812     if( (EXPR_IS_MEASURABLE( exp ) == 1) && (ESUPPL_WAS_COMB_COUNTED( exp->suppl ) == 0) ) {
00813       
00814       /* Calculate current expression combination coverage */
00815       if( !expression_is_static_only( exp ) ) {
00816     
00817         uint64 index;
00818 
00819         if( EXPR_IS_COMB( exp ) == 1 ) {
00820           if( exp_op_info[exp->op].suppl.is_comb == AND_COMB ) {
00821             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00822             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00823             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_FALSE( exp->left->suppl ) << UL_MOD(index);
00824             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00825             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00826             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_FALSE( exp->right->suppl ) << UL_MOD(index);
00827             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00828             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00829             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)exp->suppl.part.eval_11 << UL_MOD(index);
00830           } else if( exp_op_info[exp->op].suppl.is_comb == OR_COMB ) {
00831             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00832             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00833             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_TRUE( exp->left->suppl ) << UL_MOD(index);
00834             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00835             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00836             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_TRUE( exp->right->suppl ) << UL_MOD(index);
00837             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00838             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00839             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)exp->suppl.part.eval_00 << UL_MOD(index);
00840           } else {
00841             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00842             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00843             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)exp->suppl.part.eval_00 << UL_MOD(index);
00844             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00845             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00846             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)exp->suppl.part.eval_01 << UL_MOD(index);
00847             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00848             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00849             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)exp->suppl.part.eval_10 << UL_MOD(index);
00850             index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00851             rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00852             comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)exp->suppl.part.eval_11 << UL_MOD(index);
00853           }
00854         } else if( EXPR_IS_EVENT( exp ) == 1 ) {
00855           index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00856           rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00857           comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_TRUE( exp->suppl ) << UL_MOD(index);
00858         } else {
00859           index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00860           rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00861           comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_TRUE( exp->suppl ) << UL_MOD(index);
00862           index = comp_cov->cps_index[CP_TYPE_LOGIC]++;
00863           rank_check_index( CP_TYPE_LOGIC, index, __LINE__ );
00864           comp_cov->cps[CP_TYPE_LOGIC][UL_DIV(index)] |= (ulong)ESUPPL_WAS_FALSE( exp->suppl ) << UL_MOD(index);
00865         }
00866   
00867       }
00868   
00869     }
00870 
00871     /* Set the counted bit */
00872     exp->suppl.part.comb_cntd = 1;
00873 
00874   }
00875 
00876   PROFILE_END;
00877 
00878 }

static void rank_gather_comp_cdd_cov ( funit_inst inst,
comp_cdd_cov comp_cov 
) [static]

Gathers all coverage point information from the given functional unit instance and populates the specified compressed CDD coverage structure accordingly.

References funit_inst_s::child_head, combination_reset_counted_expr_tree(), statement_s::exp, FALSE, func_unit_s::fsm_head, func_iter_dealloc(), func_iter_get_next_statement(), func_iter_init(), funit_inst_s::funit, funit_is_unnamed(), funit_inst_s::next, fsm_link_s::next, sig_link_s::next, statement_s::part, PROFILE, PROFILE_END, rank_gather_expression_cov(), rank_gather_fsm_cov(), rank_gather_signal_cov(), sig_link_s::sig, func_unit_s::sig_head, statement_s::suppl, fsm_s::table, fsm_link_s::table, and TRUE.

Referenced by rank_read_cdd().

01008   { PROFILE(RANK_GATHER_COMP_CDD_COV);
01009 
01010   sig_link*   sigl;   /* Pointer to signal link */
01011   fsm_link*   fsml;   /* Pointer to FSM link */
01012   funit_inst* child;  /* Pointer to current child instance */
01013 
01014   /* Don't gather information for placeholder instances */
01015   if( inst->funit != NULL ) {
01016 
01017     /* Gather coverage information from expressions */
01018     if( !funit_is_unnamed( inst->funit ) ) {
01019       func_iter  fi;
01020       statement* stmt;
01021 
01022       /* First, clear the comb_cntd bits in all of the expressions */
01023       func_iter_init( &fi, inst->funit, TRUE, FALSE );
01024       while( (stmt = func_iter_get_next_statement( &fi )) != NULL ) {
01025         combination_reset_counted_expr_tree( stmt->exp );
01026       }
01027       func_iter_dealloc( &fi );
01028 
01029       /* Then populate the comp_cov structure, accordingly */
01030       func_iter_init( &fi, inst->funit, TRUE, FALSE );
01031       while( (stmt = func_iter_get_next_statement( &fi )) != NULL ) {
01032         rank_gather_expression_cov( stmt->exp, stmt->suppl.part.excluded, comp_cov );
01033       }
01034       func_iter_dealloc( &fi );
01035     }
01036 
01037     /* Gather coverage information from signals */
01038     sigl = inst->funit->sig_head;
01039     while( sigl != NULL ) {
01040       rank_gather_signal_cov( sigl->sig, comp_cov );
01041       sigl = sigl->next;
01042     }
01043 
01044     /* Gather coverage information from FSMs */
01045     fsml = inst->funit->fsm_head;
01046     while( fsml != NULL ) {
01047       rank_gather_fsm_cov( fsml->table->table, comp_cov );
01048       fsml = fsml->next;
01049     }
01050 
01051   }
01052 
01053   /* Gather coverage information from children */
01054   child = inst->child_head;
01055   while( child != NULL ) {
01056     rank_gather_comp_cdd_cov( child, comp_cov );
01057     child = child->next;
01058   }
01059 
01060   PROFILE_END;
01061 
01062 }

static void rank_gather_expression_cov ( expression exp,
unsigned int  exclude,
comp_cdd_cov comp_cov 
) [static]

Gathers line and combinational logic coverage point information from the given expression and populates the specified compressed CDD coverage structure accordingly.

Parameters:
exp Pointer to expression to gather coverage information from
exclude Specifies whether line coverage information should be excluded
comp_cov Pointer to compressed CDD coverage structure to populate

References CP_TYPE_LINE, comp_cdd_cov_s::cps, comp_cdd_cov_s::cps_index, expression_s::exec_num, EXP_OP_CASE, EXP_OP_CASEX, EXP_OP_CASEZ, EXP_OP_DEFAULT, EXP_OP_DELAY, EXP_OP_FORK, EXP_OP_JOIN, EXP_OP_NB_CALL, EXP_OP_NOOP, expression_s::line, expression_s::op, esuppl_u::part, PROFILE, PROFILE_END, rank_check_index(), rank_gather_comb_cov(), esuppl_u::root, expression_s::suppl, UL_DIV, and UL_MOD.

Referenced by rank_gather_comp_cdd_cov().

00888   { PROFILE(RANK_GATHER_EXPRESSION_COV);
00889 
00890   /* Calculate line coverage information (NOTE:  we currently ignore the excluded status of the line) */
00891   if( (exp->suppl.part.root == 1) &&
00892       (exp->op != EXP_OP_DELAY)   &&
00893       (exp->op != EXP_OP_CASE)    &&
00894       (exp->op != EXP_OP_CASEX)   &&
00895       (exp->op != EXP_OP_CASEZ)   &&
00896       (exp->op != EXP_OP_DEFAULT) &&
00897       (exp->op != EXP_OP_NB_CALL) &&
00898       (exp->op != EXP_OP_FORK)    &&
00899       (exp->op != EXP_OP_JOIN)    &&
00900       (exp->op != EXP_OP_NOOP)    &&
00901       (exp->line != 0) ) {
00902     uint64 index = comp_cov->cps_index[CP_TYPE_LINE]++;
00903     rank_check_index( CP_TYPE_LINE, index, __LINE__ );
00904     if( (exp->exec_num > 0) || exclude ) {
00905       comp_cov->cps[CP_TYPE_LINE][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00906     }
00907   }
00908 
00909   /* Calculate combinational logic coverage information */
00910   rank_gather_comb_cov( exp, comp_cov );
00911 
00912   PROFILE_END;
00913 
00914 }

static void rank_gather_fsm_cov ( fsm_table table,
comp_cdd_cov comp_cov 
) [static]

Gathers the FSM coverage points from the given FSM and populates the compressed CDD coverage structure accordingly.

Parameters:
table Pointer to FSM table to gather coverage information from
comp_cov Pointer to compressed CDD coverage structure to populate

References fsm_table_s::arcs, CP_TYPE_FSM, comp_cdd_cov_s::cps, comp_cdd_cov_s::cps_index, asuppl_u::excluded, free_safe, fsm_table_arc_s::from, asuppl_u::hit, fsuppl_u::known, malloc_safe, fsm_table_s::num_arcs, fsm_table_s::num_fr_states, asuppl_u::part, fsuppl_u::part, PROFILE, PROFILE_END, rank_check_index(), fsm_table_arc_s::suppl, fsm_table_s::suppl, UL_DIV, and UL_MOD.

Referenced by rank_gather_comp_cdd_cov().

00923   { PROFILE(RANK_GATHER_FSM_COV);
00924 
00925   /* We can only create a compressed version of FSM coverage information if it is known */
00926   if( table->suppl.part.known == 0 ) {
00927 
00928     int*         state_hits = (int*)malloc_safe( sizeof( int ) * table->num_fr_states );
00929     unsigned int i;
00930 
00931     /* Initialize state_hits array */
00932     for( i=0; i<table->num_fr_states; i++ ) {
00933       state_hits[i] = 0;
00934     }
00935 
00936     /* Iterate through arc transition array and count unique hits */
00937     for( i=0; i<table->num_arcs; i++ ) {
00938       uint64 index;
00939       if( (table->arcs[i]->suppl.part.hit || table->arcs[i]->suppl.part.excluded) ) {
00940         if( state_hits[table->arcs[i]->from]++ == 0 ) {
00941           index = comp_cov->cps_index[CP_TYPE_FSM]++;
00942           rank_check_index( CP_TYPE_FSM, index, __LINE__ );
00943           comp_cov->cps[CP_TYPE_FSM][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00944         }
00945         index = comp_cov->cps_index[CP_TYPE_FSM]++;
00946         rank_check_index( CP_TYPE_FSM, index, __LINE__ );
00947         comp_cov->cps[CP_TYPE_FSM][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00948       } else {
00949         if( state_hits[table->arcs[i]->from]++ == 0 ) {
00950           index = comp_cov->cps_index[CP_TYPE_FSM]++;
00951           rank_check_index( CP_TYPE_FSM, index, __LINE__ );
00952         }
00953         index = comp_cov->cps_index[CP_TYPE_FSM]++;
00954         rank_check_index( CP_TYPE_FSM, index, __LINE__ );
00955       }
00956     }
00957 
00958     /* Deallocate state_hits array */
00959     free_safe( state_hits, (sizeof( int ) * table->num_fr_states) );
00960 
00961   }
00962 
00963   PROFILE_END;
00964 
00965 }

static void rank_gather_signal_cov ( vsignal sig,
comp_cdd_cov comp_cov 
) [static]

Gathers all coverage point information from the given signal and populates the comp_cov structure accordingly.

Parameters:
sig Pointer to signal to gather coverage information from
comp_cov Pointer to compressed CDD coverage structure to populate

References CP_TYPE_MEM, CP_TYPE_TOGGLE, comp_cdd_cov_s::cps, comp_cdd_cov_s::cps_index, vsuppl_u::data_type, vsignal_s::dim, ssuppl_u::excluded, dim_range_s::lsb, ssuppl_u::mba, dim_range_s::msb, vsuppl_u::part, ssuppl_u::part, vsignal_s::pdim_num, PROFILE, PROFILE_END, rank_check_index(), SSUPPL_TYPE_ENUM, SSUPPL_TYPE_MEM, SSUPPL_TYPE_PARAM, SSUPPL_TYPE_PARAM_REAL, vector_s::suppl, vsignal_s::suppl, ssuppl_u::type, vsignal_s::udim_num, vector_s::ul, UL_DIV, UL_MOD, vector_s::value, vsignal_s::value, VDATA_UL, vector_mem_rw_count(), VTYPE_INDEX_MEM_TOG01, VTYPE_INDEX_MEM_TOG10, VTYPE_INDEX_SIG_TOG01, VTYPE_INDEX_SIG_TOG10, and vector_s::width.

Referenced by rank_gather_comp_cdd_cov().

00690   { PROFILE(RANK_GATHER_SIGNAL_COV);
00691 
00692   /* Populate toggle coverage information */
00693   if( (sig->suppl.part.type != SSUPPL_TYPE_PARAM)      &&
00694       (sig->suppl.part.type != SSUPPL_TYPE_PARAM_REAL) &&
00695       (sig->suppl.part.type != SSUPPL_TYPE_ENUM)       &&
00696       (sig->suppl.part.type != SSUPPL_TYPE_MEM)        &&
00697       (sig->suppl.part.mba == 0) ) {
00698 
00699     unsigned int i;
00700     if( sig->suppl.part.excluded == 1 ) {
00701       for( i=0; i<sig->value->width; i++ ) {
00702         uint64 index = comp_cov->cps_index[CP_TYPE_TOGGLE]++;
00703         rank_check_index( CP_TYPE_TOGGLE, index, __LINE__ );
00704         comp_cov->cps[CP_TYPE_TOGGLE][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00705         index = comp_cov->cps_index[CP_TYPE_TOGGLE]++;
00706         rank_check_index( CP_TYPE_TOGGLE, index, __LINE__ );
00707         comp_cov->cps[CP_TYPE_TOGGLE][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00708       }
00709     } else {
00710       switch( sig->value->suppl.part.data_type ) {
00711         case VDATA_UL :
00712           for( i=0; i<sig->value->width; i++ ) {
00713             uint64 index = comp_cov->cps_index[CP_TYPE_TOGGLE]++;
00714             rank_check_index( CP_TYPE_TOGGLE, index, __LINE__ );
00715             comp_cov->cps[CP_TYPE_TOGGLE][UL_DIV(index)] |= ((sig->value->value.ul[UL_DIV(i)][VTYPE_INDEX_SIG_TOG01] >> UL_MOD(i)) & (ulong)0x1) << UL_MOD(index);
00716             index = comp_cov->cps_index[CP_TYPE_TOGGLE]++;
00717             rank_check_index( CP_TYPE_TOGGLE, index, __LINE__ );
00718             comp_cov->cps[CP_TYPE_TOGGLE][UL_DIV(index)] |= ((sig->value->value.ul[UL_DIV(i)][VTYPE_INDEX_SIG_TOG10] >> UL_MOD(i)) & (ulong)0x1) << UL_MOD(index);
00719           }
00720         break;
00721         default :  assert( 0 );  break;
00722       }
00723     }
00724 
00725   }
00726 
00727   /* Populate memory coverage information */
00728   if( (sig->suppl.part.type == SSUPPL_TYPE_MEM) && (sig->udim_num > 0) ) {
00729 
00730     unsigned int i;
00731     unsigned int pwidth = 1;
00732 
00733     for( i=(sig->udim_num); i<(sig->udim_num + sig->pdim_num); i++ ) {
00734       if( sig->dim[i].msb > sig->dim[i].lsb ) {
00735         pwidth *= (sig->dim[i].msb - sig->dim[i].lsb) + 1;
00736       } else {
00737         pwidth *= (sig->dim[i].lsb - sig->dim[i].msb) + 1;
00738       }
00739     }
00740 
00741     /* Calculate total number of addressable elements and their write/read information */
00742     for( i=0; i<sig->value->width; i+=pwidth ) {
00743       if( sig->suppl.part.excluded == 1 ) {
00744         uint64 index = comp_cov->cps_index[CP_TYPE_MEM]++;
00745         rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00746         comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00747         index = comp_cov->cps_index[CP_TYPE_MEM]++;
00748         rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00749         comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00750       } else {
00751         unsigned int wr = 0;
00752         unsigned int rd = 0;
00753         uint64       index;
00754         vector_mem_rw_count( sig->value, (int)i, (int)((i + pwidth) - 1), &wr, &rd );
00755         index = comp_cov->cps_index[CP_TYPE_MEM]++;
00756         rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00757         comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= (ulong)((wr > 0) ? 1 : 0) << UL_MOD(index);
00758         index = comp_cov->cps_index[CP_TYPE_MEM]++;
00759         rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00760         comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= (ulong)((rd > 0) ? 1 : 0) << UL_MOD(index);
00761       }
00762     }
00763 
00764     /* Calculate toggle coverage information for the memory */
00765     if( sig->suppl.part.excluded == 1 ) {
00766       for( i=0; i<sig->value->width; i++ ) {
00767         uint64 index = comp_cov->cps_index[CP_TYPE_MEM]++;
00768         rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00769         comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00770         index = comp_cov->cps_index[CP_TYPE_MEM]++;
00771         rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00772         comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= (ulong)0x1 << UL_MOD(index);
00773       }
00774     } else {
00775       switch( sig->value->suppl.part.data_type ) {
00776         case VDATA_UL :
00777           for( i=0; i<sig->value->width; i++ ) {  
00778             uint64 index = comp_cov->cps_index[CP_TYPE_MEM]++;
00779             rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00780             comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= ((sig->value->value.ul[UL_DIV(i)][VTYPE_INDEX_MEM_TOG01] >> UL_MOD(i)) & (ulong)0x1) << UL_MOD(index);
00781             index = comp_cov->cps_index[CP_TYPE_MEM]++;
00782             rank_check_index( CP_TYPE_MEM, index, __LINE__ );
00783             comp_cov->cps[CP_TYPE_MEM][UL_DIV(index)] |= ((sig->value->value.ul[UL_DIV(i)][VTYPE_INDEX_MEM_TOG10] >> UL_MOD(i)) & (ulong)0x1) << UL_MOD(index);
00784           }
00785           break;
00786         default :  assert( 0 );  break;
00787       } 
00788     }   
00789         
00790   }   
00791 
00792   PROFILE_END;
00793 
00794 }

static void rank_output ( comp_cdd_cov **  comp_cdds,
unsigned int  comp_cdd_num 
) [static]

Outputs the ranking of the CDD files to the output file specified from the rank command line.

Parameters:
comp_cdds Pointer to array of ranked CDD coverage structures
comp_cdd_num Number of allocated structures in comp_cdds array

References CP_TYPE_NUM, FALSE, FATAL, flag_names_only, free_safe, gen_char_string(), longest_name_len, malloc_safe, NORMAL, num_cps, print_output(), PROFILE, PROFILE_END, rank_file, Throw, comp_cdd_cov_s::timesteps, TRUE, comp_cdd_cov_s::unique_cps, user_msg, and USER_MSG_LENGTH.

Referenced by command_rank().

01569   { PROFILE(RANK_OUTPUT);
01570 
01571   FILE*        ofile;
01572   unsigned int rv;
01573 
01574   if( rank_file == NULL ) {
01575     print_output( "\nGenerating report output to standard output...", NORMAL, __FILE__, __LINE__ );
01576   } else {
01577     rv = snprintf( user_msg, USER_MSG_LENGTH, "\nGenerating report file \"%s\"...", rank_file );
01578     assert( rv < USER_MSG_LENGTH );
01579     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01580   }
01581 
01582   if( (ofile = ((rank_file == NULL) ? stdout : fopen( rank_file, "w" ))) != NULL ) {
01583 
01584     unsigned int rv;
01585     unsigned int i;
01586     uint64       acc_timesteps  = 0;
01587     uint64       acc_unique_cps = 0;
01588     bool         unique_found   = TRUE;
01589     uint64       total_cps      = 0;
01590 
01591     /* Calculate the total number of coverage points */
01592     for( i=0; i<CP_TYPE_NUM; i++ ) {
01593       total_cps += num_cps[i];
01594     }
01595 
01596     /* If we are outputting to standard output, make sure we have a few newlines for readability purposes */
01597     if( ofile == stdout ) {
01598       fprintf( ofile, "\n\n\n" );
01599     }
01600 
01601     if( flag_names_only ) {
01602 
01603       for( i=0; i<comp_cdd_num; i++ ) {
01604         if( comp_cdds[i]->unique_cps > 0 ) {
01605           fprintf( ofile, "%s\n", comp_cdds[i]->cdd_name );
01606         }
01607       }
01608 
01609     } else {
01610 
01611       char* str;
01612       char  format[100];
01613 
01614       /* Allocate memory for a spacing string */
01615       str = (char*)malloc_safe( longest_name_len + 1 );
01616 
01617       /* Header information output */
01618       fprintf( ofile, "                                           ::::::::::::::::::::::::::::::::::::::::::::::::::::\n" );
01619       fprintf( ofile, "                                           ::                                                ::\n" );
01620       fprintf( ofile, "                                           ::     Covered -- Simulation Ranked Run Order     ::\n" );
01621       fprintf( ofile, "                                           ::                                                ::\n" );
01622       fprintf( ofile, "                                           ::::::::::::::::::::::::::::::::::::::::::::::::::::\n\n\n" );
01623       fprintf( ofile, "\n" );
01624 
01625       /* Calculate and display reduction status */
01626       i = 0;
01627       while( (i<comp_cdd_num) && ((comp_cdds[i]->unique_cps > 0) || comp_cdds[i]->required) ) i++;
01628       if( i == comp_cdd_num ) {
01629         fprintf( ofile, "No reduction occurred\n" );
01630       } else {
01631         uint64       total_timesteps  = 0;
01632         uint64       ranked_timesteps = 0;
01633         unsigned int col1, col2, j;
01634         char         str[30];
01635         char         fmt[4096];
01636 
01637         /* Calculated total_timesteps and ranked_timesteps */
01638         for( j=0; j<comp_cdd_num; j++ ) {
01639           total_timesteps += comp_cdds[j]->timesteps;
01640           if( (comp_cdds[j]->unique_cps > 0) || comp_cdds[j]->required ) {
01641             ranked_timesteps = total_timesteps;
01642           }
01643         }
01644 
01645         /* Figure out the largest number for the first column */
01646         /*@-duplicatequals -formatcode -formattype@*/
01647         rv = snprintf( str, 30, "%" FMT64 "u", total_timesteps );   col1 = strlen( str );
01648         assert( rv < 30 );
01649         rv = snprintf( str, 30, "%" FMT64 "u", ranked_timesteps );  col2 = strlen( str );
01650         /*@=duplicatequals =formatcode =formattype@*/
01651         assert( rv < 30 );
01652 
01653         /* Create line for CDD files */
01654         rv = snprintf( fmt, 4096, "* Reduced %%%uu CDD files down to %%%uu needed to maintain coverage (%%3.0f%%%% reduction, %%5.1fx improvement)\n", col1, col2 );
01655         assert( rv < 4096 );
01656         fprintf( ofile, fmt, comp_cdd_num, i, (((comp_cdd_num - i) / (float)comp_cdd_num) * 100), (comp_cdd_num / (float)i) );
01657 
01658         /* Create line for timesteps */
01659         rv = snprintf( fmt, 4096, "* Reduced %%%ullu timesteps down to %%%ullu needed to maintain coverage (%%3.0f%%%% reduction, %%5.1fx improvement)\n", col1, col2 );
01660         assert( rv < 4096 );
01661         fprintf( ofile, fmt, total_timesteps, ranked_timesteps, (((total_timesteps - ranked_timesteps) / (double)total_timesteps) * 100), (total_timesteps / (double)ranked_timesteps) );
01662       }
01663       fprintf( ofile, "\n" );
01664       gen_char_string( str, '-', (longest_name_len - 3) );
01665       fprintf( ofile, "-----------+-------------------------------------------+---------%s------------------------------------------\n", str );
01666       gen_char_string( str, ' ', (longest_name_len >> 1) );
01667       fprintf( ofile, "           |                ACCUMULATIVE               |         %s               CDD\n", str );
01668       gen_char_string( str, '-', (longest_name_len - 3) );
01669       fprintf( ofile, "Simulation |-------------------------------------------+---------%s------------------------------------------\n", str );
01670       gen_char_string( str, ' ', (longest_name_len - 3) );
01671       fprintf( ofile, "Order      |        Hit /      Total     %%   Timesteps |  R  Name%s        Hit /      Total     %%   Timesteps\n", str );
01672       gen_char_string( str, '-', (longest_name_len - 3) );
01673       fprintf( ofile, "-----------+-------------------------------------------+---------%s------------------------------------------\n", str );
01674       fprintf( ofile, "\n" );
01675 
01676       /* Calculate a string format */
01677       rv = snprintf( format, 100, "%%10u   %%10llu   %%10llu  %%3.0f%%%%  %%10llu    %%c  %%-%us  %%10llu   %%10llu  %%3.0f%%%%  %%10llu\n", longest_name_len );
01678       assert( rv < 100 );
01679 
01680       for( i=0; i<comp_cdd_num; i++ ) {
01681         acc_timesteps  += comp_cdds[i]->timesteps; 
01682         acc_unique_cps += comp_cdds[i]->unique_cps;
01683         if( (comp_cdds[i]->unique_cps == 0) && unique_found && !comp_cdds[i]->required ) {
01684           fprintf( ofile, "\n---------------------------------------  The following CDD files add no additional coverage  ----------------------------------------------\n\n" );
01685           unique_found = FALSE;
01686         }
01687         fprintf( ofile, format,
01688                 (i + 1),
01689                 acc_unique_cps,
01690                 total_cps,
01691                 ((acc_unique_cps / (float)total_cps) * 100),
01692                 acc_timesteps,
01693                 (comp_cdds[i]->required ? '*' : ' '),
01694                 comp_cdds[i]->cdd_name,
01695                 comp_cdds[i]->total_cps,
01696                 total_cps,
01697                 ((comp_cdds[i]->total_cps / (float)total_cps) * 100),
01698                 comp_cdds[i]->timesteps );
01699       }
01700       fprintf( ofile, "\n\n" );
01701 
01702       /* Deallocate the spacing string */
01703       free_safe( str, (longest_name_len + 1) );
01704 
01705     }
01706 
01707     /* Close the file if it was opened via fopen */
01708     if( rank_file != NULL ) {
01709       rv = fclose( ofile );
01710       assert( rv == 0 );
01711     }
01712 
01713   } else {
01714 
01715     rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to open ranking file \"%s\" for writing", rank_file );
01716     assert( rv < USER_MSG_LENGTH );
01717     print_output( user_msg, FATAL, __FILE__, __LINE__ );
01718     Throw 0;
01719 
01720   }
01721 
01722   PROFILE_END;
01723 
01724 }

static bool rank_parse_args ( int  argc,
int  last_arg,
const char **  argv 
) [static]
Returns:
Returns TRUE if help option was found.
Exceptions:
anonymous Throw Throw Throw

Parses the score argument list, placing all parsed values into global variables. If an argument is found that is not valid for the rank operation, an error message is displayed to the user.

Parameters:
argc Number of arguments in argument list argv
last_arg Index of last parsed argument from list
argv Argument list passed to this program

References Catch_anonymous, cdd_type_set, cdd_type_weight, check_option_value(), cp_depth, CP_TYPE_ASSERT, CP_TYPE_FSM, CP_TYPE_LINE, CP_TYPE_LOGIC, CP_TYPE_MEM, CP_TYPE_TOGGLE, directory_exists(), directory_load(), FALSE, FATAL, file_exists(), flag_names_only, free_safe, is_legal_filename(), str_link_s::next, print_output(), rank_file, rank_usage(), rank_verbose, read_command_file(), str_link_s::str, str_link_add(), str_link_delete_list(), str_link_find(), strdup_safe, str_link_s::suppl, Throw, TRUE, Try, user_msg, USER_MSG_LENGTH, and WARNING.

Referenced by command_rank().

00300   {
00301 
00302   int       i;
00303   unsigned  rank_in_num = 0;
00304   str_link* strl;
00305   str_link* ext_head    = NULL;
00306   str_link* ext_tail    = NULL;
00307   str_link* dir_head    = NULL;
00308   str_link* dir_tail    = NULL;
00309   bool      help_found  = FALSE;
00310 
00311   i = last_arg + 1;
00312 
00313   while( (i < argc) && !help_found ) {
00314 
00315     if( strncmp( "-h", argv[i], 2 ) == 0 ) {
00316 
00317       rank_usage();
00318       help_found = TRUE;
00319 
00320     } else if( strncmp( "-o", argv[i], 2 ) == 0 ) {
00321 
00322       if( check_option_value( argc, argv, i ) ) {
00323         i++;
00324         if( rank_file != NULL ) {
00325           print_output( "Only one -o option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00326         } else {
00327           if( is_legal_filename( argv[i] ) ) {
00328             rank_file = strdup_safe( argv[i] );
00329           } else {
00330             unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Output file \"%s\" is unwritable", argv[i] );
00331             assert( rv < USER_MSG_LENGTH );
00332             print_output( user_msg, FATAL, __FILE__, __LINE__ );
00333             Throw 0;
00334           }
00335         }
00336       } else {
00337         Throw 0;
00338       } 
00339 
00340     } else if( strncmp( "-f", argv[i], 2 ) == 0 ) {
00341 
00342       if( check_option_value( argc, argv, i ) ) {
00343         char**       arg_list = NULL;
00344         int          arg_num  = 0;
00345         unsigned int j;
00346         i++;
00347         Try {
00348           read_command_file( argv[i], &arg_list, &arg_num );
00349           help_found = rank_parse_args( arg_num, -1, (const char**)arg_list );
00350         } Catch_anonymous {
00351           for( j=0; j<arg_num; j++ ) {
00352             free_safe( arg_list[j], (strlen( arg_list[j] ) + 1) );
00353           }
00354           free_safe( arg_list, (sizeof( char* ) * arg_num) );
00355           Throw 0;
00356         }
00357         for( j=0; j<arg_num; j++ ) {
00358           free_safe( arg_list[j], (strlen( arg_list[j] ) + 1) );
00359         }
00360         free_safe( arg_list, (sizeof( char* ) * arg_num) );
00361       } else {
00362         Throw 0;
00363       }
00364 
00365     } else if( strncmp( "-required-list", argv[i], 14 ) == 0 ) {
00366 
00367       if( check_option_value( argc, argv, i ) ) {
00368         i++;
00369         if( file_exists( argv[i] ) ) {
00370           FILE* file;
00371           if( (file = fopen( argv[i], "r" )) != NULL ) {
00372             char         fname[4096];
00373             unsigned int rv;
00374             while( fscanf( file, "%s", fname ) == 1 ) {
00375               if( file_exists( fname ) ) {
00376                 str_link* strl;
00377                 if( (strl = str_link_find( fname, rank_in_head )) == NULL ) {
00378                   strl = str_link_add( strdup_safe( fname ), &rank_in_head, &rank_in_tail );
00379                 }
00380                 strl->suppl = 1;
00381               } else {
00382                 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Filename (%s) specified in -required file (%s) does not exist", fname, argv[i] );
00383                 assert( rv < USER_MSG_LENGTH );
00384                 print_output( user_msg, FATAL, __FILE__, __LINE__ );
00385                 Throw 0;
00386               }
00387             }
00388             rv = fclose( file );
00389             assert( rv == 0 );
00390           } else {
00391             unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to read -required-list file (%s)", argv[i] );
00392             assert( rv < USER_MSG_LENGTH );
00393             print_output( user_msg, FATAL, __FILE__, __LINE__ );
00394             Throw 0;
00395           }
00396         } else {
00397           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Filename specified for -required-list option (%s) does not exist", argv[i] );
00398           assert( rv < USER_MSG_LENGTH );
00399           print_output( user_msg, FATAL, __FILE__, __LINE__ );
00400           Throw 0;
00401         }
00402       
00403       } else {
00404         Throw 0;
00405       }
00406 
00407     } else if( strncmp( "-required-cdd", argv[i], 13 ) == 0 ) {
00408 
00409       if( check_option_value( argc, argv, i ) ) {
00410         i++;
00411         if( file_exists( argv[i] ) ) {
00412           str_link* strl;
00413           if( (strl = str_link_find( argv[i], rank_in_head )) == NULL ) {
00414             strl = str_link_add( strdup_safe( argv[i] ), &rank_in_head, &rank_in_tail );
00415           }
00416           strl->suppl = 1;
00417         } else {
00418           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to read -required-cdd file (%s)", argv[i] );
00419           assert( rv < USER_MSG_LENGTH );
00420           print_output( user_msg, FATAL, __FILE__, __LINE__ );
00421           Throw 0;
00422         }
00423       } else {
00424         Throw 0;
00425       }
00426 
00427     } else if( strncmp( "-ext", argv[i], 4 ) == 0 ) {
00428 
00429       if( check_option_value( argc, argv, i ) ) {
00430         i++;
00431         (void)str_link_add( strdup_safe( argv[i] ), &ext_head, &ext_tail );
00432       } else {
00433         Throw 0;
00434       }
00435 
00436     } else if( strncmp( "-weight-line", argv[i], 12 ) == 0 ) {
00437 
00438       if( check_option_value( argc, argv, i ) ) {
00439         i++;
00440         if( cdd_type_set[CP_TYPE_LINE] ) {
00441           print_output( "Only one -weight-line option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00442         } else {
00443           if( sscanf( argv[i], "%u", &cdd_type_weight[CP_TYPE_LINE] ) != 1 ) {
00444             print_output( "Value specified after -weight-line must be a number", FATAL, __FILE__, __LINE__ );
00445             Throw 0;
00446           } else {
00447             cdd_type_set[CP_TYPE_LINE] = TRUE;
00448           }
00449         }
00450       } else {
00451         Throw 0;
00452       }
00453 
00454     } else if( strncmp( "-weight-toggle", argv[i], 14 ) == 0 ) {
00455   
00456       if( check_option_value( argc, argv, i ) ) {
00457         i++;
00458         if( cdd_type_set[CP_TYPE_TOGGLE] ) {
00459           print_output( "Only one -weight-toggle option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00460         } else {
00461           if( sscanf( argv[i], "%u", &cdd_type_weight[CP_TYPE_TOGGLE] ) != 1 ) {
00462             print_output( "Value specified after -weight-toggle must be a number", FATAL, __FILE__, __LINE__ );
00463             Throw 0;
00464           } else {
00465             cdd_type_set[CP_TYPE_TOGGLE] = TRUE;
00466           }
00467         }
00468       } else {
00469         Throw 0;
00470       }
00471 
00472     } else if( strncmp( "-weight-memory", argv[i], 14 ) == 0 ) {
00473 
00474       if( check_option_value( argc, argv, i ) ) {
00475         i++;
00476         if( cdd_type_set[CP_TYPE_MEM] ) {
00477           print_output( "Only one -weight-memory option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00478         } else {
00479           if( sscanf( argv[i], "%u", &cdd_type_weight[CP_TYPE_MEM] ) != 1 ) {
00480             print_output( "Value specified after -weight-memory must be a number", FATAL, __FILE__, __LINE__ );
00481             Throw 0;
00482           } else {
00483             cdd_type_set[CP_TYPE_MEM] = TRUE;
00484           }
00485         }
00486       } else {
00487         Throw 0;
00488       }
00489 
00490     } else if( strncmp( "-weight-comb", argv[i], 12 ) == 0 ) {
00491 
00492       if( check_option_value( argc, argv, i ) ) {
00493         i++; 
00494         if( cdd_type_set[CP_TYPE_LOGIC] ) {
00495           print_output( "Only one -weight-comb option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00496         } else {
00497           if( sscanf( argv[i], "%u", &cdd_type_weight[CP_TYPE_LOGIC] ) != 1 ) {
00498             print_output( "Value specified after -weight-comb must be a number", FATAL, __FILE__, __LINE__ );
00499             Throw 0;
00500           } else {
00501             cdd_type_set[CP_TYPE_LOGIC] = TRUE;
00502           }
00503         }
00504       } else {
00505         Throw 0;
00506       }
00507 
00508     } else if( strncmp( "-weight-fsm", argv[i], 11 ) == 0 ) {
00509 
00510       if( check_option_value( argc, argv, i ) ) {
00511         i++;
00512         if( cdd_type_set[CP_TYPE_FSM] ) {
00513           print_output( "Only one -weight-fsm option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00514         } else {
00515           if( sscanf( argv[i], "%u", &cdd_type_weight[CP_TYPE_FSM] ) != 1 ) {
00516             print_output( "Value specified after -weight-fsm must be a number", FATAL, __FILE__, __LINE__ );
00517             Throw 0;
00518           } else {
00519             cdd_type_set[CP_TYPE_FSM] = TRUE;
00520           }
00521         }
00522       } else {
00523         Throw 0;
00524       }
00525 
00526     } else if( strncmp( "-weight-assert", argv[i], 14 ) == 0 ) {
00527 
00528       if( check_option_value( argc, argv, i ) ) {
00529         i++;
00530         if( cdd_type_set[CP_TYPE_ASSERT] ) {
00531           print_output( "Only one -weight-assert option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00532         } else {
00533           if( sscanf( argv[i], "%u", &cdd_type_weight[CP_TYPE_ASSERT] ) != 1 ) {
00534             print_output( "Value specified after -weight-assert must be a number", FATAL, __FILE__, __LINE__ );
00535             Throw 0;
00536           } else {
00537             cdd_type_set[CP_TYPE_ASSERT] = TRUE;
00538           }
00539         }
00540       } else {
00541         Throw 0;
00542       }
00543 
00544     } else if( strncmp( "-names-only", argv[i], 11 ) == 0 ) {
00545 
00546       flag_names_only = TRUE;
00547 
00548     } else if( strncmp( "-depth", argv[i], 6 ) == 0 ) {
00549 
00550       if( check_option_value( argc, argv, i ) ) {
00551         i++;
00552         if( cp_depth != 0 ) {
00553           print_output( "Only one -depth option is allowed on the rank command-line.  Using first value...", WARNING, __FILE__, __LINE__ );
00554         } else {
00555           if( (sscanf( argv[i], "%u", &cp_depth ) != 1) || (cp_depth == 0) ) {
00556             print_output( "Value specified after -depth must be a positive, non-zero number", FATAL, __FILE__, __LINE__ );
00557             Throw 0;
00558           }
00559         }
00560       } else {
00561         Throw 0;
00562       }
00563 
00564     } else if( strncmp( "-d", argv[i], 2 ) == 0 ) {
00565 
00566       if( check_option_value( argc, argv, i ) ) {
00567         i++;
00568         if( directory_exists( argv[i] ) ) {
00569           (void)str_link_add( strdup_safe( argv[i] ), &dir_head, &dir_tail );
00570         } else {
00571           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Specified -d directory (%s) does not exist", argv[i] );
00572           assert( rv < USER_MSG_LENGTH );
00573           print_output( user_msg, FATAL, __FILE__, __LINE__ );
00574           Throw 0;
00575         }
00576       } else {
00577         Throw 0;
00578       }
00579 
00580     } else if( strncmp( "-v", argv[i], 2 ) == 0 ) {
00581 
00582       rank_verbose = TRUE;
00583 
00584     } else if( strncmp( "-", argv[i], 1 ) == 0 ) {
00585 
00586       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unknown rank option (%s) specified.", argv[i] );
00587       assert( rv < USER_MSG_LENGTH );
00588       print_output( user_msg, FATAL, __FILE__, __LINE__ );
00589       Throw 0;
00590 
00591     } else {
00592 
00593       /* The name of a file to rank */
00594       if( file_exists( argv[i] ) ) {
00595 
00596         if( str_link_find( argv[i], rank_in_head ) == NULL ) {
00597 
00598           /* Add the specified rank file to the list */
00599           (void)str_link_add( strdup_safe( argv[i] ), &rank_in_head, &rank_in_tail );
00600 
00601         }
00602 
00603       } else {
00604 
00605         unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "CDD file (%s) does not exist", argv[i] );
00606         assert( rv < USER_MSG_LENGTH );
00607         print_output( user_msg, FATAL, __FILE__, __LINE__ );
00608         Throw 0;
00609 
00610       }
00611 
00612     }
00613 
00614     i++;
00615 
00616   }
00617 
00618   if( !help_found ) {
00619 
00620     Try {
00621 
00622       /* Load any ranking files found in specified directories */
00623       strl = dir_head;
00624       while( strl != NULL ) {
00625         directory_load( strl->str, ext_head, &rank_in_head, &rank_in_tail );
00626         strl = strl->next;
00627       }
00628 
00629     } Catch_anonymous {
00630       str_link_delete_list( ext_head );
00631       str_link_delete_list( dir_head );
00632       Throw 0;
00633     }
00634 
00635     /* Count the number of files being ranked */
00636     strl = rank_in_head;
00637     while( strl != NULL ) {
00638       rank_in_num++;
00639       strl = strl->next;
00640     }
00641 
00642     /* Check to make sure that the user specified at least two files to rank */
00643     if( rank_in_num < 2 ) {
00644       print_output( "Must specify at least two CDD files to rank", FATAL, __FILE__, __LINE__ );
00645       Throw 0;
00646     }
00647 
00648     /* If no -depth option was specified, set its value to 1 */
00649     if( cp_depth == 0 ) {
00650       cp_depth = 1;
00651     }
00652 
00653   }
00654 
00655   /* Deallocate the temporary lists */
00656   str_link_delete_list( ext_head );
00657   str_link_delete_list( dir_head );
00658 
00659   return( help_found );
00660 
00661 }

static void rank_perform ( comp_cdd_cov **  comp_cdds,
unsigned int  comp_cdd_num 
) [static]

Performs the task of ranking the CDD files and rearranging them in the comp_cdds array such that the first CDD file is located at index 0.

Parameters:
comp_cdds Pointer to array of compressed CDD coverage structures to rank
comp_cdd_num Number of allocated structures in comp_cdds array

References calloc_safe, CP_TYPE_ASSERT, CP_TYPE_FSM, CP_TYPE_LINE, CP_TYPE_LOGIC, CP_TYPE_MEM, CP_TYPE_NUM, CP_TYPE_TOGGLE, debug_mode, free_safe, malloc_safe_nolimit, NORMAL, num_cps, print_output(), PROFILE, PROFILE_END, quiet_mode, rank_count_cps(), rank_perform_greedy_sort(), rank_perform_weighted_selection(), rank_selected_cdd_cov(), rank_verbose, terse_mode, comp_cdd_cov_s::total_cps, UL_DIV, UL_MOD, comp_cdd_cov_s::unique_cps, user_msg, and USER_MSG_LENGTH.

Referenced by command_rank().

01360   { PROFILE(RANK_PERFORM);
01361 
01362   unsigned int i, j, k;
01363   uint16*      ranked_merged;
01364   uint16*      unranked_merged;
01365   uint16       merged_index = 0;
01366   uint64       total        = 0;
01367   uint64       total_hitable;
01368   unsigned int next_cdd     = 0;
01369   unsigned int most_unique;
01370   unsigned int count;
01371   unsigned int cdds_ranked  = 0;
01372   timer*       atimer       = NULL;
01373   unsigned int rv;
01374 
01375   if( ((!quiet_mode && !terse_mode) || debug_mode) && !rank_verbose ) {
01376     printf( "Ranking CDD files " );
01377     rv = fflush( stdout );
01378     assert( rv == 0 );
01379   }
01380 
01381   /* Calculate the total number of needed merged entries to store accumulated information */
01382   for( i=0; i<CP_TYPE_NUM; i++ ) {
01383     total += num_cps[i];
01384   }
01385   assert( total > 0 );
01386 
01387   /* Allocate merged array */
01388   ranked_merged   = (uint16*)calloc_safe( total, sizeof( uint16 ) );
01389   unranked_merged = (uint16*)malloc_safe_nolimit( sizeof( uint16 ) * total );
01390 
01391   if( rank_verbose ) {
01392     /*@-duplicatequals -formatcode -formattype@*/
01393     rv = snprintf( user_msg, USER_MSG_LENGTH, "\nRanking %u CDD files with %" FMT64 "u coverage points (%" FMT64 "u line, %" FMT64 "u toggle, %" FMT64 "u memory, %" FMT64 "u logic, %" FMT64 "u FSM, %" FMT64 "u assertion)",
01394               comp_cdd_num, total, num_cps[CP_TYPE_LINE], num_cps[CP_TYPE_TOGGLE], num_cps[CP_TYPE_MEM], num_cps[CP_TYPE_LOGIC], num_cps[CP_TYPE_FSM], num_cps[CP_TYPE_ASSERT] );
01395     /*@=duplicatequals =formatcode =formattype@*/
01396     assert( rv < USER_MSG_LENGTH );
01397     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01398   }
01399 
01400   /* Step 1 - Initialize merged results array, calculate uniqueness and total values of each compressed CDD coverage structure */
01401   for( i=0; i<CP_TYPE_NUM; i++ ) {
01402     for( j=0; j<num_cps[i]; j++ ) {
01403       uint16       bit_total = 0;
01404       unsigned int set_cdd;
01405       for( k=0; k<comp_cdd_num; k++ ) {
01406         if( (comp_cdds[k]->cps[i][UL_DIV(j)] & ((ulong)0x1 << UL_MOD(j))) != 0 ) {
01407           comp_cdds[k]->total_cps++;
01408           set_cdd = k;
01409           bit_total++;
01410         }
01411       }
01412       unranked_merged[merged_index++] = bit_total;
01413 
01414       /* If we found exactly one CDD file that hit this coverage point, mark it in the corresponding CDD file */
01415       if( bit_total == 1 ) {
01416         comp_cdds[set_cdd]->unique_cps++;
01417       }
01418     }
01419   }
01420 
01421   if( rank_verbose ) {
01422     total_hitable = rank_count_cps( unranked_merged, total ); 
01423     /*@-duplicatequals -formatcode +ignorequals@*/
01424     rv = snprintf( user_msg, USER_MSG_LENGTH, "Ignoring %" FMT64 "u coverage points that were not hit by any CDD file", (total - total_hitable) );
01425     /*@=duplicatequals =formatcode =ignorequals@*/
01426     assert( rv < USER_MSG_LENGTH );
01427     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01428 
01429     print_output( "\nPhase 1:  Adding user-required files", NORMAL, __FILE__, __LINE__ );
01430     rv = fflush( stdout );
01431     assert( rv == 0 );
01432     timer_clear( &atimer );
01433     timer_start( &atimer );
01434   }
01435 
01436   /* Step 2 - Immediately rank all of the required CDDs */
01437   for( i=0; i<comp_cdd_num; i++ ) {
01438     if( comp_cdds[i]->required ) {
01439       rank_selected_cdd_cov( comp_cdds, comp_cdd_num, ranked_merged, unranked_merged, next_cdd, i );
01440       next_cdd++;
01441     }
01442   }
01443 
01444   if( rank_verbose ) {
01445     uint64 ranked_cps = rank_count_cps( ranked_merged, total );
01446     timer_stop( &atimer );
01447     rv = snprintf( user_msg, USER_MSG_LENGTH, "  Ranked %u CDD files (Total ranked: %u, Remaining: %u)", next_cdd, next_cdd, (comp_cdd_num - next_cdd) );
01448     assert( rv < USER_MSG_LENGTH );
01449     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01450     /*@-duplicatequals -formatcode -formattype@*/
01451     rv = snprintf( user_msg, USER_MSG_LENGTH, "  %" FMT64 "u points covered, %" FMT64 "u points remaining", ranked_cps, (total_hitable - ranked_cps) );
01452     /*@=duplicatequals =formatcode =formattype@*/
01453     assert( rv < USER_MSG_LENGTH );
01454     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01455     rv = snprintf( user_msg, USER_MSG_LENGTH, "Completed phase 1 in %s", timer_to_string( atimer ) );
01456     assert( rv < USER_MSG_LENGTH );
01457     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01458   
01459     count = next_cdd;
01460     print_output( "\nPhase 2:  Adding files that hit unique coverage points", NORMAL, __FILE__, __LINE__ );
01461     rv = fflush( stdout );
01462     assert( rv == 0 );
01463     timer_clear( &atimer );
01464     timer_start( &atimer );
01465   }
01466 
01467   /* Step 3 - Start with the most unique CDDs */
01468   do {
01469     most_unique = next_cdd;
01470     for( i=(next_cdd+1); i<comp_cdd_num; i++ ) {
01471       if( comp_cdds[i]->unique_cps > comp_cdds[most_unique]->unique_cps ) {
01472         most_unique = i;
01473       }
01474     }
01475     if( comp_cdds[most_unique]->unique_cps > 0 ) {
01476       rank_selected_cdd_cov( comp_cdds, comp_cdd_num, ranked_merged, unranked_merged, next_cdd, most_unique );
01477       next_cdd++;
01478     }
01479   } while( (next_cdd < comp_cdd_num) && (comp_cdds[most_unique]->unique_cps > 0) );
01480 
01481   if( rank_verbose ) {
01482     uint64 ranked_cps = rank_count_cps( ranked_merged, total );
01483     timer_stop( &atimer );
01484     rv = snprintf( user_msg, USER_MSG_LENGTH, "  Ranked %u CDD files (Total ranked: %u, Remaining: %u)", (next_cdd - count), next_cdd, (comp_cdd_num - next_cdd) );
01485     assert( rv < USER_MSG_LENGTH );
01486     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01487     /*@-duplicatequals -formatcode -formattype@*/
01488     rv = snprintf( user_msg, USER_MSG_LENGTH, "  %" FMT64 "u points covered, %" FMT64 "u points remaining", ranked_cps, (total_hitable - ranked_cps) );
01489     /*@=duplicatequals =formatcode =formattype@*/
01490     assert( rv < USER_MSG_LENGTH );
01491     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01492     rv = snprintf( user_msg, USER_MSG_LENGTH, "Completed phase 2 in %s", timer_to_string( atimer ) );
01493     assert( rv < USER_MSG_LENGTH );
01494     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01495    
01496     count = next_cdd;
01497     print_output( "\nPhase 3:  Adding files that hit remaining coverage points and eliminating redundant files", NORMAL, __FILE__, __LINE__ );
01498     rv = fflush( stdout );
01499     assert( rv == 0 );
01500     timer_clear( &atimer );
01501     timer_start( &atimer );
01502   }
01503 
01504   /* Step 4 - Select coverage based on user-specified factors */
01505   if( next_cdd < comp_cdd_num ) {
01506     rank_perform_weighted_selection( comp_cdds, comp_cdd_num, ranked_merged, unranked_merged, next_cdd, &cdds_ranked );
01507   }
01508 
01509   if( rank_verbose ) {
01510     uint64 ranked_cps = rank_count_cps( ranked_merged, total );
01511     timer_stop( &atimer );
01512     rv = snprintf( user_msg, USER_MSG_LENGTH, "  Ranked %u CDD files (Total ranked: %u, Eliminated: %u)", cdds_ranked, (count + cdds_ranked), (comp_cdd_num - (count + cdds_ranked)) );
01513     assert( rv < USER_MSG_LENGTH );
01514     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01515     /*@-duplicatequals -formatcode -formattype@*/
01516     rv = snprintf( user_msg, USER_MSG_LENGTH, "  %" FMT64 "u points covered, %" FMT64 "u points remaining", ranked_cps, (total_hitable - ranked_cps) );
01517     /*@=duplicatequals =formatcode =formattype@*/
01518     assert( rv < USER_MSG_LENGTH );
01519     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01520     rv = snprintf( user_msg, USER_MSG_LENGTH, "Completed phase 3 in %s", timer_to_string( atimer ) );
01521     assert( rv < USER_MSG_LENGTH );
01522     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01523 
01524     print_output( "\nPhase 4:  Sorting CDD files selected for ranking (no reductions)", NORMAL, __FILE__, __LINE__ );
01525     rv = fflush( stdout );
01526     assert( rv == 0 );
01527     timer_clear( &atimer );
01528     timer_start( &atimer );
01529   }
01530 
01531   /* Step 5 - Re-sort the list using a greedy algorithm */
01532   rank_perform_greedy_sort( comp_cdds, comp_cdd_num, ranked_merged, total );
01533 
01534   if( rank_verbose ) {
01535     timer_stop( &atimer );
01536     rv = snprintf( user_msg, USER_MSG_LENGTH, "Completed phase 4 in %s", timer_to_string( atimer ) );
01537     assert( rv < USER_MSG_LENGTH );
01538     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01539     rv = fflush( stdout );
01540     assert( rv == 0 );
01541     free_safe( atimer, sizeof( timer ) );
01542 
01543     if( comp_cdd_num == (count + cdds_ranked) ) {
01544       rv = snprintf( user_msg, USER_MSG_LENGTH, "\nSUMMARY:  No reduction occurred.  %u needed/required", (count + cdds_ranked) );
01545       assert( rv < USER_MSG_LENGTH );
01546     } else {
01547       rv = snprintf( user_msg, USER_MSG_LENGTH, "\nSUMMARY:  Reduced %u CDD files down to %u needed/required", comp_cdd_num, (count + cdds_ranked) );
01548       assert( rv < USER_MSG_LENGTH );
01549     }
01550     print_output( user_msg, NORMAL, __FILE__, __LINE__ );
01551   }
01552 
01553   /* Deallocate merged CDD coverage structure */
01554   free_safe( ranked_merged,   (sizeof( uint16 ) * total ) );
01555   free_safe( unranked_merged, (sizeof( uint16 ) * total ) );
01556 
01557   PROFILE_END;
01558 
01559 }

static void rank_perform_greedy_sort ( comp_cdd_cov **  comp_cdds,
unsigned int  comp_cdd_num,
uint16 *  ranked_merged,
uint64  num_ranked 
) [static]

Re-sorts the compressed CDD coverage array to order them based on a "most coverage points per timestep" basis.

Parameters:
comp_cdds Pointer to compressed CDD coverage structure array to re-sort
comp_cdd_num Number of elements in comp-cdds array
ranked_merged Array for recalculating uniqueness of sorted elements
num_ranked Number of elements in ranked_merged array

References cp_depth, CP_TYPE_NUM, num_cps, PROFILE, PROFILE_END, UL_DIV, UL_MOD, and comp_cdd_cov_s::unique_cps.

Referenced by rank_perform().

01280   { PROFILE(RANK_PERFORM_GREEDY_SORT);
01281 
01282   unsigned int  i, j, k, l;
01283   unsigned int  best;
01284   uint64        x;
01285   comp_cdd_cov* tmp;
01286 
01287   /* First, reset the ranked_merged array */
01288   for( x=0; x<num_ranked; x++ ) {
01289     ranked_merged[x] = 0;
01290   }
01291 
01292   /* Rank based on most unique from previously ranked CDDs */
01293   for( i=0; i<comp_cdd_num; i++ ) {
01294     best = i;
01295     for( j=i; j<comp_cdd_num; j++ ) {
01296       x = 0;
01297       comp_cdds[j]->unique_cps = 0;
01298       for( k=0; k<CP_TYPE_NUM; k++ ) {
01299         for( l=0; l<num_cps[k]; l++ ) {
01300           if( comp_cdds[j]->cps[k][UL_DIV(l)] & ((ulong)0x1 << UL_MOD(l)) ) {
01301             if( ranked_merged[x] < cp_depth ) {
01302               comp_cdds[j]->unique_cps++;
01303             }
01304           }
01305           x++;
01306         }
01307       }
01308       if( (comp_cdds[best]->unique_cps < comp_cdds[j]->unique_cps) ||
01309           ((comp_cdds[best]->unique_cps == comp_cdds[j]->unique_cps) && (comp_cdds[best]->timesteps < comp_cdds[j]->timesteps)) ||
01310           ((comp_cdds[best]->unique_cps == 0) && !comp_cdds[best]->required && !comp_cdds[i]->required) ) {
01311         best = j;
01312       }
01313     }
01314     tmp             = comp_cdds[i];
01315     comp_cdds[i]    = comp_cdds[best];
01316     comp_cdds[best] = tmp;
01317     x = 0;
01318     for( j=0; j<CP_TYPE_NUM; j++ ) {
01319       for( k=0; k<num_cps[j]; k++ ) {
01320         if( comp_cdds[i]->cps[j][UL_DIV(k)] & ((ulong)0x1 << UL_MOD(k)) ) {
01321           ranked_merged[x]++;
01322         }
01323         x++;
01324       }
01325     }
01326   }
01327 
01328   PROFILE_END;
01329 
01330 }

static void rank_perform_weighted_selection ( comp_cdd_cov **  comp_cdds,
unsigned int  comp_cdd_num,
uint16 *  ranked_merged,
uint16 *  unranked_merged,
unsigned int  next_cdd,
unsigned int *  cdds_ranked 
) [static]

Performs ranking according to scores that are calculated from the user-specified weights and the amount of coverage points left to be hit. Ranks all compressed CDD coverage structures between next_cdd and the end of the array (comp_cdd_num - 1), inclusive.

Parameters:
comp_cdds Reference to partially sorted list of compressed CDD coverage structures to sort
comp_cdd_num Number of compressed CDD coverage structures in the comp_cdds array
ranked_merged Array of ranked merged information from all of the compressed CDD coverage structures
unranked_merged Array of unranked merged information from all of the compressed CDD coverage structures
next_cdd Next index in comp_cdds array to set
cdds_ranked Number of CDDs that were ranked with unique coverage in this function

References cdd_type_weight, cp_depth, CP_TYPE_NUM, FALSE, num_cps, PROFILE, PROFILE_END, rank_selected_cdd_cov(), comp_cdd_cov_s::score, TRUE, UL_DIV, and UL_MOD.

Referenced by rank_perform().

01225   { PROFILE(RANK_PERFORM_WEIGHTED_SELECTION);
01226 
01227   /* Perform this loop for each remaining coverage file */
01228   for( ; next_cdd<comp_cdd_num; next_cdd++ ) {
01229 
01230     unsigned int i, j, k;
01231     unsigned int highest_score = next_cdd;
01232 
01233     /* Calculate current scores */
01234     for( i=next_cdd; i<comp_cdd_num; i++ ) {
01235       bool   unique_found = FALSE;
01236       uint64 x            = 0;
01237       comp_cdds[i]->score = 0;
01238       for( j=0; j<CP_TYPE_NUM; j++ ) {
01239         unsigned int total = 0;
01240         for( k=0; k<num_cps[j]; k++ ) {
01241           if( unranked_merged[x] > 0 ) {
01242             if( comp_cdds[i]->cps[j][UL_DIV(k)] & ((ulong)0x1 << UL_MOD(k)) ) {
01243               total++;
01244               if( ranked_merged[x] < cp_depth ) {
01245                 unique_found = TRUE;
01246               }
01247             }
01248           }
01249           x++;
01250         }
01251         comp_cdds[i]->score += ((total / (float)comp_cdds[i]->timesteps) * 100) * cdd_type_weight[j];
01252       }
01253       if( (comp_cdds[i]->score > comp_cdds[highest_score]->score) && unique_found ) {
01254         highest_score = i;
01255       }
01256     } 
01257 
01258     /* Store the selected CDD into the next slot of the comp_cdds array */
01259     rank_selected_cdd_cov( comp_cdds, comp_cdd_num, ranked_merged, unranked_merged, next_cdd, highest_score );
01260 
01261     /* Increment the number of unique_cps ranked */
01262     if( comp_cdds[next_cdd]->unique_cps > 0 ) {
01263       (*cdds_ranked)++;
01264     }
01265 
01266   }
01267 
01268   PROFILE_END;
01269 
01270 }

static void rank_read_cdd ( const char *  cdd_name,
bool  required,
bool  first,
comp_cdd_cov ***  comp_cdds,
unsigned int *  comp_cdd_num 
) [static]

Parses the given CDD name and stores its coverage point information in a compressed format.

Parameters:
cdd_name Filename of CDD file to read in
required Specifies if CDD file is required to be ranked
first Set to TRUE if this if the first CDD being read
comp_cdds Pointer to compressed CDD array
comp_cdd_num Number of compressed CDD structures in comp_cdds array

References bind_perform(), Catch_anonymous, CP_TYPE_NUM, db_close(), db_read(), FATAL, inst_link_s::inst, db_s::inst_head, inst_link_s::next, num_cps, num_timesteps, print_output(), PROFILE, PROFILE_END, rank_calc_num_cps(), rank_create_comp_cdd_cov(), rank_dealloc_comp_cdd_cov(), rank_gather_comp_cdd_cov(), READ_MODE_REPORT_NO_MERGE, realloc_safe, report_gather_instance_stats(), Throw, TRUE, Try, user_msg, and USER_MSG_LENGTH.

Referenced by command_rank().

01073   { PROFILE(RANK_READ_CDD);
01074 
01075   comp_cdd_cov* comp_cov = NULL;
01076 
01077   Try {
01078 
01079     inst_link* instl;
01080     uint64     tmp_nums[CP_TYPE_NUM] = {0};
01081 
01082     /* Read in database */
01083     (void)db_read( cdd_name, READ_MODE_REPORT_NO_MERGE );
01084     bind_perform( TRUE, 0 );
01085 
01086     /* Calculate the num_cps array if we are the first or check our coverage points to verify that they match */
01087     instl = db_list[0]->inst_head;
01088     while( instl != NULL ) {
01089       report_gather_instance_stats( instl->inst );
01090       if( first ) {
01091         rank_calc_num_cps( instl->inst, num_cps );
01092       } else {
01093         rank_calc_num_cps( instl->inst, tmp_nums );
01094       }
01095       instl = instl->next;
01096     }
01097 
01098     /* If we are not the first CDD file being read in, verify that our values match */
01099     if( !first ) {
01100       unsigned int i;
01101       for( i=0; i<CP_TYPE_NUM; i++ ) {
01102         if( num_cps[i] != tmp_nums[i] ) {
01103           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "CDD file \"%s\" does not match previously read CDD files", cdd_name );
01104           assert( rv < USER_MSG_LENGTH );
01105           print_output( user_msg, FATAL, __FILE__, __LINE__ );
01106           Throw 0;
01107         }
01108       }
01109     }
01110 
01111     /* Allocate the memory needed for the compressed CDD coverage structure */
01112     comp_cov = rank_create_comp_cdd_cov( cdd_name, required, num_timesteps );
01113 
01114     /* Finally, populate compressed CDD coverage structure with coverage information from database signals */
01115     instl = db_list[0]->inst_head;
01116     while( instl != NULL ) {
01117       rank_gather_comp_cdd_cov( instl->inst, comp_cov );
01118       instl = instl->next;
01119     }
01120 
01121     /* Add compressed CDD coverage structure to array */
01122     *comp_cdds = (comp_cdd_cov**)realloc_safe( *comp_cdds, (sizeof( comp_cdd_cov* ) * (*comp_cdd_num)), (sizeof( comp_cdd_cov* ) * (*comp_cdd_num + 1)) );
01123     (*comp_cdds)[*comp_cdd_num] = comp_cov;
01124     (*comp_cdd_num)++;
01125 
01126   } Catch_anonymous {
01127     db_close();
01128     rank_dealloc_comp_cdd_cov( comp_cov );
01129     Throw 0;
01130   }
01131 
01132   /* Close the database */
01133   db_close();
01134 
01135   PROFILE_END;
01136 
01137 }

static void rank_selected_cdd_cov ( comp_cdd_cov **  comp_cdds,
unsigned int  comp_cdd_num,
uint16 *  ranked_merged,
uint16 *  unranked_merged,
unsigned int  next_cdd,
unsigned int  selected_cdd 
) [static]

Sorts the selected CDD coverage structure into the comp_cdds list and performs post-placement calculations.

Parameters:
comp_cdds Pointer to array of compressed CDD coverage structures being sorted
comp_cdd_num Total number of elements in comp_cdds array
ranked_merged Array of merged information for ranked CDDs
unranked_merged Array of merged information for unranked CDDs
next_cdd Index into comp_cdds array that the selected CDD should be stored at
selected_cdd Index into comp_cdds array of the selected CDD for ranking

References cp_depth, CP_TYPE_NUM, debug_mode, num_cps, PROFILE, PROFILE_END, quiet_mode, rank_verbose, terse_mode, UL_DIV, UL_MOD, and comp_cdd_cov_s::unique_cps.

Referenced by rank_perform(), and rank_perform_weighted_selection().

01151   { PROFILE(RANK_SELECTED_CDD_COV);
01152 
01153   unsigned int        i, j;
01154   uint64              merged_index = 0;
01155   static unsigned int dots_output  = 0;
01156   comp_cdd_cov*       tmp;
01157 
01158   /* Output status indicator, if necessary */
01159   if( ((!quiet_mode && !terse_mode) || debug_mode) && !rank_verbose ) {
01160     while( ((unsigned int)(((next_cdd + 1) / (float)comp_cdd_num) * 100) - (dots_output * 10)) >= 10 ) { 
01161       unsigned int rv;
01162       printf( "." );
01163       rv = fflush( stdout );
01164       assert( rv == 0 );
01165       dots_output++;
01166     }
01167   }
01168 
01169   /* Move the most unique CDD to the next position */
01170   tmp                     = comp_cdds[next_cdd];
01171   comp_cdds[next_cdd]     = comp_cdds[selected_cdd];
01172   comp_cdds[selected_cdd] = tmp;
01173 
01174   /* Zero out uniqueness value */
01175   comp_cdds[next_cdd]->unique_cps = 0;
01176 
01177   /* Subtract all of the set coverage points from the merged value */
01178   for( i=0; i<CP_TYPE_NUM; i++ ) {
01179     for( j=0; j<num_cps[i]; j++ ) {
01180       if( unranked_merged[merged_index] > 0 ) {
01181         if( comp_cdds[next_cdd]->cps[i][UL_DIV(j)] & ((ulong)0x1 << UL_MOD(j)) ) {
01182           /*
01183            If we have not seen this coverage point get hit the needed "depth" amount in the ranked
01184            list, increment the unique_cps value for the selected compressed CDD coverage structure.
01185           */
01186           if( ranked_merged[merged_index] < cp_depth ) {
01187             comp_cdds[next_cdd]->unique_cps++;
01188           }
01189           unranked_merged[merged_index]--;
01190           ranked_merged[merged_index]++;
01191         }
01192       }
01193       merged_index++;
01194     }
01195   }
01196 
01197   if( ((!quiet_mode && !terse_mode) || debug_mode) && !rank_verbose ) {
01198     if( (next_cdd + 1) == comp_cdd_num ) {
01199       unsigned int rv;
01200       if( dots_output < 10 ) {
01201         printf( "." );
01202       }
01203       printf( "\n" );
01204       rv = fflush( stdout );
01205       assert( rv == 0 );
01206     }
01207   }
01208 
01209   PROFILE_END;
01210 
01211 }

static void rank_usage (  )  [static]

Outputs usage information to standard output for rank command.

Referenced by rank_parse_args().

00237                          {
00238 
00239   printf( "\n" );
00240   printf( "Usage:  covered rank (-h | ([<options>] <database_to_rank> <database_to_rank>+)\n" );
00241   printf( "\n" );
00242   printf( "   -h                           Displays this help information.\n" );
00243   printf( "\n" );
00244   printf( "   Options:\n" );
00245   printf( "      -depth <number>           Specifies the minimum number of CDD files to hit each coverage point.\n" );
00246   printf( "                                  The value of <number> should be a value of 1 or more.  Default is 1.\n" );
00247   printf( "      -names-only               If specified, outputs only the needed CDD filenames that need to be\n" );
00248   printf( "                                  run in the order they need to be run.  If this option is not set, a\n" );
00249   printf( "                                  report-style output is provided with additional information.\n" );
00250   printf( "      -f <filename>             Name of file containing additional arguments to parse.\n" );
00251   printf( "      -required-list <filename> Name of file containing list of CDD files which are required to be in the\n" );
00252   printf( "                                  list of ranked CDDs to be run.\n" );
00253   printf( "      -required-cdd <filename>  Name of CDD file that is required to be in the list of ranked CDDs to be run.\n" );
00254   printf( "      -d <directory>            Directory to search for CDD files to include.  This option is used in\n" );
00255   printf( "                                  conjunction with the -ext option which specifies the file extension\n" );
00256   printf( "                                  to use for determining which files in the directory are CDD files.\n" );
00257   printf( "      -ext <extension>          Used in conjunction with the -d option.  If no -ext options are specified\n" );
00258   printf( "                                  on the command-line, the default value of '.cdd' is used.  Note that\n" );
00259   printf( "                                  a period (.) should be specified.\n" );
00260   printf( "      -o <filename>             Name of file to output ranking information to.  Default is stdout.\n" );
00261   printf( "      -weight-line <number>     Specifies a relative weighting for line coverage used to rank\n" );
00262   printf( "                                  non-unique coverage points.  A value of 0 removes line coverage\n" );
00263   printf( "                                  from ranking consideration.  Default value is 1.\n" );
00264   printf( "      -weight-toggle <number>   Specifies a relative weighting for toggle coverage used to rank\n" );
00265   printf( "                                  non-unique coverage points.  A value of 0 removes toggle coverage\n" );
00266   printf( "                                  from ranking consideration.  Default value is 1.\n" );
00267   printf( "      -weight-memory <number>   Specifies a relative weighting for memory coverage used to rank\n" );
00268   printf( "                                  non-unique coverage points.  A value of 0 removes memory coverage\n" );
00269   printf( "                                  from ranking consideration.  Default value is 1.\n" );
00270   printf( "      -weight-comb <number>     Specifies a relative weighting for combinational logic coverage used\n" );
00271   printf( "                                  to rank non-unique coverage points.  A value of 0 removes combinational\n" );
00272   printf( "                                  logic coverage from ranking consideration.  Default value is 1.\n" );
00273   printf( "      -weight-fsm <number>      Specifies a relative weighting for FSM state/state transition coverage\n" );
00274   printf( "                                  used to rank non-unique coverage points.  A value of 0 removes FSM\n" );
00275   printf( "                                  coverage from ranking consideration.  Default value is 1.\n" );
00276   printf( "      -weight-assert <number>   Specifies a relative weighting for assertion coverage used to rank\n" );
00277   printf( "                                  non-unique coverage points.  A value of 0 removes assertion coverage\n" );
00278   printf( "                                  from ranking consideration.  Default value is 0.\n" );
00279   printf( "      -v                        Outputs verbose information during the rank selection process.  This output\n" );
00280   printf( "                                  is not for debugging purposes, but rather gives the user insight into\n" );
00281   printf( "                                  what's going on \"behind the scenes\" during the ranking process.\n" );
00282   printf( "\n" );
00283 
00284 }


Variable Documentation

Controls whether multi-expressions are used or not.

Referenced by combination_get_tree_stats(), and command_rank().

bool cdd_type_set[CP_TYPE_NUM] = {0} [static]

Set to TRUE when the user has specified the corresponding weight value on the command-line. Allows us to display a warning message to the user when multiple values are specified.

Referenced by rank_parse_args().

unsigned int cdd_type_weight[CP_TYPE_NUM] = {1,1,1,1,1,0} [static]

Array containing the weights to be used for each of the CDD metric types.

Referenced by rank_parse_args(), and rank_perform_weighted_selection().

unsigned int cp_depth = 0 [static]

Specifies the number of CDDs that must hit each coverage point before a CDD will be considered unneeded.

Referenced by rank_parse_args(), rank_perform_greedy_sort(), rank_perform_weighted_selection(), and rank_selected_cdd_cov().

Array of database pointers storing all currently loaded databases.

If set to TRUE, causes debug information to be spewed to screen.

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.

bool flag_names_only = FALSE [static]

If set to TRUE, outputs only the names of the CDD files in the order that they should be run. This value is set to TRUE when the -names_only option is specified.

Referenced by rank_output(), and rank_parse_args().

Holds the largest number of bytes in allocation at one period of time.

Referenced by calloc_safe1(), command_rank(), command_score(), malloc_safe1(), malloc_safe_nolimit1(), realloc_safe1(), and strdup_safe1().

unsigned int longest_name_len = 0 [static]

Specifies the string length of the longest CDD name

Referenced by rank_create_comp_cdd_cov(), and rank_output().

uint64 num_cps[CP_TYPE_NUM] = {0} [static]

Array containing the number of coverage points for each metric for all compressed CDD coverage structures.

Referenced by rank_check_index(), rank_create_comp_cdd_cov(), rank_dealloc_comp_cdd_cov(), rank_output(), rank_perform(), rank_perform_greedy_sort(), rank_perform_weighted_selection(), rank_read_cdd(), and rank_selected_cdd_cov().

uint64 num_timesteps

Specifies the number of timesteps that have transpired during this simulation.

Referenced by db_do_timestep(), info_db_read(), info_db_write(), and rank_read_cdd().

If set to TRUE, suppresses all non-warning/fatal error messages from being displayed.

Referenced by print_output(), rank_perform(), rank_selected_cdd_cov(), and set_quiet().

char* rank_file = NULL [static]

File to be used for outputting rank information.

Referenced by command_rank(), rank_output(), and rank_parse_args().

str_link* rank_in_head = NULL [static]

Pointer to head of list of CDD filenames that need to be read in.

str_link* rank_in_tail = NULL [static]

Pointer to tail of list of CDD filenames that need to be read in.

bool rank_verbose = FALSE [static]

If set to TRUE, outputs behind the scenes output during the rank selection process.

Referenced by command_rank(), rank_parse_args(), rank_perform(), and rank_selected_cdd_cov().

If set to a boolean value of TRUE, reports the assertion coverage for the specified database file; otherwise, omits assertion coverage from the report output.

Referenced by command_rank(), report_gather_funit_stats(), report_gather_instance_stats(), report_generate(), report_parse_args(), and report_parse_metrics().

If set to a boolean value of TRUE, reports the combinational logic coverage for the specified database file; otherwise, omits combinational logic coverage from the report output.

Referenced by command_rank(), report_gather_funit_stats(), report_gather_instance_stats(), report_generate(), and report_parse_metrics().

If set to a boolean value of TRUE, reports the finite state machine coverage for the specified database file; otherwise, omits finite state machine coverage from the report output.

Referenced by command_rank(), report_gather_funit_stats(), report_gather_instance_stats(), report_generate(), and report_parse_metrics().

If set to a boolean value of TRUE, reports the line coverage for the specified database file; otherwise, omits line coverage from the report output.

Referenced by command_rank(), report_gather_funit_stats(), report_gather_instance_stats(), report_generate(), and report_parse_metrics().

If set to a boolean value of TRUE, reports the memory coverage for the specified database file; otherwise, omits memory coverage from the report output.

Referenced by command_rank(), report_gather_funit_stats(), report_gather_instance_stats(), report_generate(), report_parse_args(), and report_parse_metrics().

If set to a boolean value of TRUE, reports the toggle coverage for the specified database file; otherwise, omits toggle coverage from the report output.

Referenced by command_rank(), report_gather_funit_stats(), report_gather_instance_stats(), report_generate(), and report_parse_metrics().

If set to TRUE, suppresses all normal messages from being displayed.

Referenced by print_output(), rank_perform(), rank_selected_cdd_cov(), and set_terse().

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:40 2010 for Covered by  doxygen 1.6.3