race.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "db.h"
#include "defines.h"
#include "expr.h"
#include "func_unit.h"
#include "link.h"
#include "obfuscate.h"
#include "ovl.h"
#include "race.h"
#include "statement.h"
#include "stmt_blk.h"
#include "util.h"
#include "vector.h"
#include "vsignal.h"

Functions

static void race_calc_assignments (statement *, int)
static race_blkrace_blk_create (int reason, int start_line, int end_line)
static bool race_find_head_statement_containing_statement_helper (statement *curr, statement *to_find)
static statementrace_find_head_statement_containing_statement (statement *stmt)
static statementrace_get_head_statement (expression *expr)
static int race_find_head_statement (statement *stmt)
static void race_calc_stmt_blk_type (expression *expr, int sb_index)
static void race_calc_expr_assignment (expression *exp, int sb_index)
static void race_handle_race_condition (expression *expr, func_unit *mod, statement *stmt, statement *base, int reason)
static void race_check_assignment_types (func_unit *mod)
static void race_check_one_block_assignment (func_unit *mod)
static void race_check_race_count ()
void race_check_modules ()
 Checks the current module for race conditions.
void race_db_write (race_blk *rb, FILE *file)
 Writes contents of specified race condition block to specified file output.
void race_db_read (char **line, func_unit *curr_mod)
 Reads contents from specified line for a race condition block and assigns the new block to the curr_mod.
void race_get_stats (race_blk *curr, unsigned int *race_total, unsigned int type_total[][RACE_TYPE_NUM])
 Get statistic information for the specified race condition block list.
static bool race_report_summary (FILE *ofile, funit_link *head)
static void race_report_verbose (FILE *ofile, funit_link *head)
void race_report (FILE *ofile, bool verbose)
 Displays report information for race condition blocks in design.
void race_collect_lines (func_unit *funit, int **slines, int **elines, int **reasons, int *line_cnt)
 Collects all of the lines in the specified module that were not verified due to race condition breach.
void race_blk_delete_list (race_blk *rb)
 Deallocates the specified race condition block from memory.

Variables

static stmt_blksb = NULL
static int sb_size
static int races_found = 0
const char * race_msgs [RACE_TYPE_NUM]
int flag_race_check
char user_msg [USER_MSG_LENGTH]
db ** db_list
unsigned int curr_db
func_unitcurr_funit
isuppl info_suppl
int stmt_conn_id
bool debug_mode
str_linkrace_ignore_mod_head
str_linkrace_ignore_mod_tail

Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
12/15/2004
The contents of this file contain functions to handle race condition checking and information handling regarding race conditions. Since race conditions can cause the Covered simulator to not provide the same run-time order as the primary Verilog simulator, we need to be able to detect when race conditions are occurring within the design. The conditions that are checked within the design during the parsing stage can be found Race Condition Violation Types.
The failure of any one of these rules will cause Covered to either display warning type messages to the user when the race condition checking flag has not been set or error messages when the race condition checking flag has been set by the user.

Function Documentation

static race_blk* race_blk_create ( int  reason,
int  start_line,
int  end_line 
) [static]
Returns:
Returns a pointer to the newly allocated race condition block.

Allocates and initializes memory for a race condition block.

Parameters:
reason Numerical reason for why race condition was detected
start_line Starting line of race condition block
end_line Ending line of race condition block

References race_blk_s::end_line, malloc_safe, race_blk_s::next, PROFILE, PROFILE_END, race_blk_s::reason, and race_blk_s::start_line.

Referenced by race_db_read(), and race_handle_race_condition().

00107   { PROFILE(RACE_BLK_CREATE);
00108 
00109   race_blk* rb;  /* Pointer to newly allocated race condition block */
00110 
00111   rb             = (race_blk*)malloc_safe( sizeof( race_blk ) );
00112   rb->reason     = reason;
00113   rb->start_line = start_line;
00114   rb->end_line   = end_line;
00115   rb->next       = NULL;
00116 
00117   PROFILE_END;
00118 
00119   return( rb );
00120 
00121 }

void race_blk_delete_list ( race_blk rb  ) 

Deallocates the specified race condition block from memory.

Recursively deallocates the specified race condition block list.

Parameters:
rb Pointer to race condition block to deallocate

References free_safe, race_blk_s::next, PROFILE, PROFILE_END, and race_blk_delete_list().

Referenced by funit_clean(), and race_blk_delete_list().

01091   { PROFILE(RACE_BLK_DELETE_LIST);
01092 
01093   if( rb != NULL ) {
01094 
01095     /* Delete the next race condition block first */
01096     race_blk_delete_list( rb->next );
01097 
01098     /* Deallocate the memory for this race condition block */
01099     free_safe( rb, sizeof( race_blk ) );
01100 
01101   }
01102 
01103   PROFILE_END;
01104 
01105 }

void race_calc_assignments ( statement stmt,
int  sb_index 
) [static]

Recursively iterates through the given statement block, searching for all assignment types used within the block.

Parameters:
stmt Pointer to statement to get assign type from
sb_index Current statement block index containing the given statement

References statement_s::conn_id, statement_s::exp, statement_s::next_false, statement_s::next_true, statement_s::part, PROFILE, PROFILE_END, race_calc_expr_assignment(), stmt_conn_id, and statement_s::suppl.

Referenced by race_calc_expr_assignment(), and race_check_modules().

00311   { PROFILE(RACE_CALC_ASSIGNMENTS);
00312 
00313   if( (stmt != NULL) && (stmt->conn_id != stmt_conn_id) ) {
00314 
00315     stmt->conn_id = stmt_conn_id;
00316 
00317     /* Calculate children statements */
00318     if( stmt->suppl.part.stop_true == 0 ) {
00319       race_calc_assignments( stmt->next_true, sb_index );
00320     }
00321     if( (stmt->suppl.part.stop_false == 0) && (stmt->next_true != stmt->next_false) ) {
00322       race_calc_assignments( stmt->next_false, sb_index );
00323     }
00324 
00325     /* Calculate assignment operator type */
00326     race_calc_expr_assignment( stmt->exp, sb_index );
00327 
00328   }
00329 
00330   PROFILE_END;
00331 
00332 }

static void race_calc_expr_assignment ( expression exp,
int  sb_index 
) [static]

Checks the given expression for its assignment type and sets the given statement block structure to the appropriate assign type value. If the given expression is a named block, iterate through that block searching for an assignment type.

Parameters:
exp Pointer to expression to check for expression assignment type
sb_index Current statement block index containing the given expression

References stmt_blk_s::bassign, expression_s::elem, EXP_OP_ASSIGN, EXP_OP_BASSIGN, EXP_OP_DASSIGN, EXP_OP_FORK, EXP_OP_NASSIGN, EXP_OP_NB_CALL, EXP_OP_TASK_CALL, func_unit_s::first_stmt, esuppl_u::for_cntrl, expression_s::funit, stmt_blk_s::nassign, expression_s::op, esuppl_u::part, PROFILE, PROFILE_END, race_calc_assignments(), expression_s::suppl, and TRUE.

Referenced by race_calc_assignments().

00287   { PROFILE(RACE_CALC_EXPR_ASSIGNMENT);
00288 
00289   switch( exp->op ) {
00290     case EXP_OP_ASSIGN    :
00291     case EXP_OP_DASSIGN   :  sb[sb_index].bassign = TRUE;  break;
00292     case EXP_OP_NASSIGN   :  sb[sb_index].nassign = TRUE;  break;
00293     case EXP_OP_BASSIGN   :  sb[sb_index].bassign = (exp->suppl.part.for_cntrl == 0);  break;
00294     case EXP_OP_TASK_CALL :
00295     case EXP_OP_FORK      :
00296     case EXP_OP_NB_CALL   :  race_calc_assignments( exp->elem.funit->first_stmt, sb_index );  break;
00297     default               :  break;
00298   }
00299 
00300   PROFILE_END;
00301 
00302 }

static void race_calc_stmt_blk_type ( expression expr,
int  sb_index 
) [static]

Recursively iterates down expression tree, searching for an expression which will indicate that its statement block is a sequential always block or a combinational always block.

Parameters:
expr Pointer to expression to check for statement block type (sequential/combinational)
sb_index Current statement block index containing the given expression

References stmt_blk_s::cmb, EXP_OP_AEDGE, EXP_OP_ALWAYS_COMB, EXP_OP_ALWAYS_LATCH, EXP_OP_NEDGE, EXP_OP_PEDGE, expression_s::left, expression_s::op, PROFILE, PROFILE_END, expression_s::right, stmt_blk_s::seq, and TRUE.

Referenced by race_check_modules().

00257   { PROFILE(RACE_CALC_STMT_BLK_TYPE);
00258 
00259   if( expr != NULL ) {
00260 
00261     /* Go to children to calculate further */
00262     race_calc_stmt_blk_type( expr->left,  sb_index );
00263     race_calc_stmt_blk_type( expr->right, sb_index );
00264 
00265     if( (expr->op == EXP_OP_PEDGE) || (expr->op == EXP_OP_NEDGE) || (expr->op == EXP_OP_ALWAYS_LATCH) ) {
00266       sb[sb_index].seq = TRUE;
00267     }
00268 
00269     if( (expr->op == EXP_OP_AEDGE) || (expr->op == EXP_OP_ALWAYS_COMB) ) {
00270       sb[sb_index].cmb = TRUE;
00271     }
00272 
00273   }
00274 
00275   PROFILE_END;
00276 
00277 }

static void race_check_assignment_types ( func_unit mod  )  [static]

Performs the race condition assignment checks for each statement block.

Parameters:
mod Pointer to functional unit to check assignment types for

References PROFILE, PROFILE_END, race_handle_race_condition(), RACE_TYPE_CMB_USES_BLOCK, RACE_TYPE_HOMOGENOUS, RACE_TYPE_MIX_USES_NON_BLOCK, RACE_TYPE_SEQ_USES_NON_BLOCK, sb_size, and stmt_blk_s::stmt.

Referenced by race_check_modules().

00479   { PROFILE(RACE_CHECK_ASSIGNMENT_TYPES);
00480 
00481   int i;  /* Loop iterator */
00482 
00483   for( i=0; i<sb_size; i++ ) {
00484 
00485     if( sb[i].stmt->suppl.part.ignore_rc == 0 ) {
00486 
00487       /* Check that a sequential logic block contains only non-blocking assignments */
00488       if( sb[i].seq && !sb[i].cmb && sb[i].bassign ) {
00489 
00490         race_handle_race_condition( sb[i].stmt->exp, mod, sb[i].stmt, sb[i].stmt, RACE_TYPE_SEQ_USES_NON_BLOCK );
00491 
00492       /* Check that a combinational logic block contains only blocking assignments */
00493       } else if( !sb[i].seq && sb[i].cmb && sb[i].nassign ) {
00494 
00495         race_handle_race_condition( sb[i].stmt->exp, mod, sb[i].stmt, sb[i].stmt, RACE_TYPE_CMB_USES_BLOCK );
00496 
00497       /* Check that mixed logic block contains only non-blocking assignments */
00498       } else if( sb[i].seq && sb[i].cmb && sb[i].bassign ) {
00499 
00500         race_handle_race_condition( sb[i].stmt->exp, mod, sb[i].stmt, sb[i].stmt, RACE_TYPE_MIX_USES_NON_BLOCK );
00501 
00502       /* Check that a statement block doesn't contain both blocking and non-blocking assignments */
00503       } else if( sb[i].bassign && sb[i].nassign ) {
00504 
00505         race_handle_race_condition( sb[i].stmt->exp, mod, sb[i].stmt, sb[i].stmt, RACE_TYPE_HOMOGENOUS );
00506 
00507       }
00508 
00509     }
00510 
00511   }
00512 
00513   PROFILE_END;
00514 
00515 }

void race_check_modules (  ) 

Checks the current module for race conditions.

Exceptions:
anonymous race_check_race_count funit_size_elements

Performs race checking for the currently loaded module. This function should be called when the endmodule keyword is detected in the current module.

References isuppl_u::assert_ovl, stmt_blk_s::bassign, stmt_blk_s::cmb, curr_db, DEBUG, debug_mode, FALSE, free_safe, funit_link_s::funit, db_s::funit_head, FUNIT_MODULE, funit_size_elements(), db_s::inst_head, inst_link_find_by_funit(), malloc_safe, func_unit_s::name, stmt_blk_s::nassign, funit_link_s::next, stmt_link_s::next, ovl_is_assertion_module(), statement_s::part, isuppl_u::part, print_output(), PROFILE, PROFILE_END, race_calc_assignments(), race_calc_stmt_blk_type(), race_check_assignment_types(), race_check_one_block_assignment(), race_check_race_count(), stmt_blk_s::remove, sb_size, stmt_blk_s::seq, stmt_blk_s::stmt, stmt_link_s::stmt, stmt_blk_add_to_remove_list(), stmt_conn_id, func_unit_s::stmt_head, str_link_find(), statement_s::suppl, and func_unit_s::type.

Referenced by parse_design().

00730                           { PROFILE(RACE_CHECK_MODULES);
00731 
00732   int         sb_index;  /* Index to statement block array */
00733   stmt_link*  curr;
00734   funit_link* modl;      /* Pointer to current module link */
00735   int         i;         /* Loop iterator */
00736   int         ignore;    /* Placeholder */
00737   funit_inst* inst;      /* Instance of this functional unit */
00738 
00739   modl = db_list[curr_db]->funit_head;
00740 
00741   while( modl != NULL ) {
00742 
00743     /* Get instance */
00744     ignore = 0;
00745     inst   = inst_link_find_by_funit( modl->funit, db_list[curr_db]->inst_head, &ignore );
00746 
00747     /* Only perform race condition checking for modules that are instantiated and are not OVL assertions and are not ignored */
00748     if( (modl->funit->type == FUNIT_MODULE) &&
00749         (inst != NULL) &&
00750         ((info_suppl.part.assert_ovl == 0) || !ovl_is_assertion_module( modl->funit )) &&
00751         (str_link_find( modl->funit->name, race_ignore_mod_head ) == NULL) ) {
00752 
00753       /* Size elements for the current module */
00754       funit_size_elements( modl->funit, inst, FALSE, FALSE );
00755 
00756       /* Clear statement block array size */
00757       sb_size = 0;
00758 
00759       /* First, get the size of the statement block array for this module */
00760       curr = modl->funit->stmt_head;
00761       while( curr != NULL ) {
00762         if( (curr->stmt->suppl.part.head == 1) &&
00763             (curr->stmt->suppl.part.is_called == 0) ) {
00764           sb_size++;
00765         }
00766         curr = curr->next;
00767       }
00768 
00769       if( sb_size > 0 ) {
00770 
00771         /* Allocate memory for the statement block array and clear current index */
00772         sb       = (stmt_blk*)malloc_safe( sizeof( stmt_blk ) * sb_size );
00773         sb_index = 0;
00774 
00775         /* Second, populate the statement block array with pointers to the head statements */
00776         curr = modl->funit->stmt_head;
00777         while( curr != NULL ) {
00778           if( (curr->stmt->suppl.part.head == 1) &&
00779               (curr->stmt->suppl.part.is_called == 0) ) {
00780             sb[sb_index].stmt    = curr->stmt;
00781             sb[sb_index].remove  = FALSE;
00782             sb[sb_index].seq     = FALSE;
00783             sb[sb_index].cmb     = FALSE;
00784             sb[sb_index].bassign = FALSE;
00785             sb[sb_index].nassign = FALSE;
00786             race_calc_stmt_blk_type( sb[sb_index].stmt->exp, sb_index );
00787             race_calc_assignments( sb[sb_index].stmt, sb_index );
00788             sb_index++; 
00789             stmt_conn_id++;
00790           }
00791           curr = curr->next;
00792         }
00793 
00794         /* Perform checks #1 - #5 */
00795         race_check_assignment_types( modl->funit );
00796 
00797         /* Perform check #6 */
00798         race_check_one_block_assignment( modl->funit );
00799 
00800         /* Cleanup statements to be removed */
00801         curr_funit = modl->funit;
00802         for( i=0; i<sb_size; i++ ) {
00803           if( sb[i].remove ) {
00804 #ifdef DEBUG_MODE
00805             if( debug_mode ) {
00806               print_output( "Removing statement block because it was found to have a race condition", DEBUG, __FILE__, __LINE__ );
00807             }
00808 #endif 
00809             stmt_blk_add_to_remove_list( sb[i].stmt );
00810           }
00811         }
00812 
00813         /* Deallocate stmt_blk list */
00814         free_safe( sb, (sizeof( stmt_blk ) * sb_size) );
00815 
00816       }
00817 
00818     }
00819 
00820     modl = modl->next;
00821 
00822   }
00823 
00824   /* Handle output if any race conditions were found */
00825   race_check_race_count();
00826 
00827   PROFILE_END;
00828 
00829 }

static void race_check_one_block_assignment ( func_unit mod  )  [static]

Verifies that every signal is assigned in only one statement block. If a signal is assigned in more than one statement block, both statement block's need to be removed from coverage consideration and a possible warning/error message generated to the user.

Parameters:
mod Pointer to module containing signals to verify

References vsignal_s::dim, ESUPPL_IS_LHS, ESUPPL_IS_ROOT, statement_s::exp, exp_link_s::exp, vsignal_s::exp_head, EXP_OP_DIM, EXP_OP_MBIT_NEG, EXP_OP_MBIT_POS, EXP_OP_MBIT_SEL, EXP_OP_RASSIGN, EXP_OP_SBIT_SEL, EXP_OP_SIG, EXP_OP_STATIC, expr_stmt_u::expr, expression_get_curr_dimension(), expression_is_bit_select(), expression_is_in_rassign(), expression_is_last_select(), FALSE, expression_s::left, dim_range_s::lsb, dim_range_s::msb, sig_link_s::next, exp_link_s::next, expression_s::op, expression_s::parent, statement_s::part, ssuppl_u::part, PROFILE, PROFILE_END, race_find_head_statement(), race_get_head_statement(), race_handle_race_condition(), RACE_TYPE_ASSIGN_IN_ONE_BLOCK1, RACE_TYPE_ASSIGN_IN_ONE_BLOCK2, stmt_blk_s::remove, expression_s::right, sig_link_s::sig, func_unit_s::sig_head, SSUPPL_TYPE_GENVAR, SSUPPL_TYPE_INOUT_NET, SSUPPL_TYPE_INOUT_REG, SSUPPL_TYPE_INPUT_NET, SSUPPL_TYPE_INPUT_REG, SSUPPL_TYPE_MEM, stmt_blk_s::stmt, statement_s::suppl, expression_s::suppl, vsignal_s::suppl, TRUE, ssuppl_u::type, vsignal_s::value, expression_s::value, vector_set_assigned(), vector_to_int(), vsignal_calc_width_for_expr(), and vector_s::width.

Referenced by race_check_modules().

00524   { PROFILE(RACE_CHECK_ONE_BLOCK_ASSIGNMENT);
00525 
00526   sig_link*  sigl;                /* Pointer to current signal */
00527   exp_link*  expl;                /* Pointer to current expression */
00528   statement* curr_stmt;           /* Pointer to current statement */
00529   int        sig_stmt;            /* Index of base signal statement in statement block array */
00530   bool       curr_race  = FALSE;  /* Set to TRUE if race condition was found in current iteration */
00531   int        lval;                /* Left expression value */
00532   int        rval;                /* Right expression value */
00533   int        exp_dim;             /* Current expression dimension */
00534   int        dim_lsb;             /* LSB of current dimension */
00535   bool       dim_be;              /* Big endianness of current dimension */
00536   int        dim_width;           /* Bit width of current dimension */
00537   int        intval;              /* Integer value */
00538 
00539   sigl = mod->sig_head;
00540   while( sigl != NULL ) {
00541 
00542     sig_stmt = -1;
00543 
00544     /* Skip checking the expressions of genvar signals */
00545     if( (sigl->sig->suppl.part.type != SSUPPL_TYPE_GENVAR) && (sigl->sig->suppl.part.type != SSUPPL_TYPE_MEM) ) {
00546 
00547       /* Iterate through expressions */
00548       expl = sigl->sig->exp_head;
00549       while( expl != NULL ) {
00550                                               
00551         /* Only look at expressions that are part of LHS and they are not part of a bit select */
00552         if( (ESUPPL_IS_LHS( expl->exp->suppl ) == 1) && !expression_is_bit_select( expl->exp ) && expression_is_last_select( expl->exp ) ) {
00553 
00554           /* Get head statement of current expression */
00555           curr_stmt = race_get_head_statement( expl->exp );
00556 
00557           /* If the head statement is being ignored from race condition checking, skip the rest */
00558           if( (curr_stmt != NULL) && (curr_stmt->suppl.part.ignore_rc == 0) ) {
00559 
00560             vector* src;
00561             int     vwidth;
00562 
00563             /* Get current dimension of the given expression */
00564             exp_dim = expression_get_curr_dimension( expl->exp );
00565   
00566             /* Calculate starting vector value bit and signal LSB/BE for LHS */
00567             if( (ESUPPL_IS_ROOT( expl->exp->suppl ) == 0) &&
00568                 (expl->exp->parent->expr->op == EXP_OP_DIM) && (expl->exp->parent->expr->right == expl->exp) ) {
00569               src    = expl->exp->parent->expr->left->value;
00570               vwidth = src->width;
00571             } else {
00572               /* Get starting vector bit from signal itself */
00573               src    = sigl->sig->value;
00574               vwidth = src->width;
00575             }
00576             if( sigl->sig->dim[exp_dim].lsb < sigl->sig->dim[exp_dim].msb ) {
00577               dim_lsb = sigl->sig->dim[exp_dim].lsb;
00578               dim_be  = FALSE;
00579             } else {
00580               dim_lsb = sigl->sig->dim[exp_dim].msb;
00581               dim_be  = TRUE;
00582             }
00583             dim_width = vsignal_calc_width_for_expr( expl->exp, sigl->sig );
00584 
00585             /*
00586              If the signal was a part select, set the appropriate misc bits to indicate what
00587              bits have been assigned.
00588             */
00589             switch( expl->exp->op ) {
00590               case EXP_OP_SIG :
00591                 if( (ESUPPL_IS_ROOT( expl->exp->suppl ) == 0) && !expression_is_in_rassign( expl->exp ) ) {
00592                   curr_race = vector_set_assigned( sigl->sig->value, (sigl->sig->value->width - 1), 0 );
00593                 }
00594               break;
00595               case EXP_OP_SBIT_SEL :
00596                 if( expl->exp->left->op == EXP_OP_STATIC ) {
00597                   intval = (vector_to_int( expl->exp->left->value ) - dim_lsb) * dim_width;
00598                   if( (intval >= 0) && ((unsigned int)intval < expl->exp->value->width) ) {
00599                     if( dim_be ) {
00600                       int lsb = (vwidth - (intval + expl->exp->value->width));
00601                       curr_race = vector_set_assigned( sigl->sig->value, ((expl->exp->value->width - 1) + lsb), lsb );
00602                     } else {
00603                       curr_race = vector_set_assigned( sigl->sig->value, ((expl->exp->value->width - 1) + intval), intval );
00604                     }
00605                   } else {
00606                     curr_race = FALSE;
00607                   }
00608                 } else { 
00609                   curr_race = vector_set_assigned( sigl->sig->value, (sigl->sig->value->width - 1), 0 );
00610                 }
00611               break;
00612               case EXP_OP_MBIT_SEL :
00613                 if( (expl->exp->left->op == EXP_OP_STATIC) && (expl->exp->right->op == EXP_OP_STATIC) ) {
00614                   intval = ((dim_be ? vector_to_int( expl->exp->left->value ) : vector_to_int( expl->exp->right->value )) - dim_lsb) * dim_width;
00615                   if( dim_be ) {
00616                     int lsb = (vwidth - (intval + expl->exp->value->width));
00617                     curr_race = vector_set_assigned( sigl->sig->value, ((expl->exp->value->width - 1) + lsb), lsb );
00618                   } else {
00619                     curr_race = vector_set_assigned( sigl->sig->value, ((expl->exp->value->width - 1) + intval), intval );
00620                   }
00621                 } else {
00622                   curr_race = vector_set_assigned( sigl->sig->value, (sigl->sig->value->width - 1), 0 );
00623                 }
00624                 break;
00625               case EXP_OP_MBIT_POS :
00626                 if( expl->exp->left->op == EXP_OP_STATIC ) {
00627                   lval = vector_to_int( expl->exp->left->value );
00628                   rval = vector_to_int( expl->exp->right->value );
00629                   curr_race = vector_set_assigned( sigl->sig->value, ((lval + rval) - sigl->sig->dim[exp_dim].lsb), (lval - sigl->sig->dim[exp_dim].lsb) );
00630                 } else {
00631                   curr_race = vector_set_assigned( sigl->sig->value, (sigl->sig->value->width - 1), 0 );
00632                 }
00633                 break;
00634               case EXP_OP_MBIT_NEG :
00635                 if( expl->exp->left->op == EXP_OP_STATIC ) {
00636                   lval = vector_to_int( expl->exp->left->value );
00637                   rval = vector_to_int( expl->exp->right->value );
00638                   curr_race = vector_set_assigned( sigl->sig->value, ((lval + 1) - sigl->sig->dim[exp_dim].lsb), (((lval - rval) + 1) - sigl->sig->dim[exp_dim].lsb) );
00639                 } else {
00640                   curr_race = vector_set_assigned( sigl->sig->value, (sigl->sig->value->width - 1), 0 );
00641                 }
00642                 break;
00643               default :
00644                 curr_race = FALSE;
00645                 break;  
00646             }
00647   
00648             /*
00649              Get expression's head statement and if the statement is not a register assignment, check for
00650              race conditions (the way that RASSIGNs are treated, they will not cause race conditions so omit
00651              them from being checked.
00652             */
00653             if( (curr_stmt != NULL) && (curr_stmt->exp->op != EXP_OP_RASSIGN) ) {
00654 
00655               /* Check to see if the current signal is already being assigned in another statement */
00656               if( sig_stmt == -1 ) {
00657 
00658                 /* Get index of base signal statement in sb array */
00659                 sig_stmt = race_find_head_statement( curr_stmt );
00660                 assert( sig_stmt != -1 );
00661   
00662                 /* Check to see if current signal is also an input port */ 
00663                 if( (sigl->sig->suppl.part.type == SSUPPL_TYPE_INPUT_NET) ||
00664                     (sigl->sig->suppl.part.type == SSUPPL_TYPE_INPUT_REG) ||
00665                     (sigl->sig->suppl.part.type == SSUPPL_TYPE_INOUT_NET) ||
00666                     (sigl->sig->suppl.part.type == SSUPPL_TYPE_INOUT_REG) || curr_race ) {
00667                   race_handle_race_condition( expl->exp, mod, curr_stmt, NULL, RACE_TYPE_ASSIGN_IN_ONE_BLOCK2 );
00668                   sb[sig_stmt].remove = TRUE;
00669                 }
00670   
00671               } else if( (sb[sig_stmt].stmt != curr_stmt) && curr_race ) {
00672   
00673                 race_handle_race_condition( expl->exp, mod, curr_stmt, sb[sig_stmt].stmt, RACE_TYPE_ASSIGN_IN_ONE_BLOCK1 );
00674                 sb[sig_stmt].remove = TRUE;
00675   
00676               }
00677   
00678             }
00679 
00680           }
00681 
00682         }
00683 
00684         expl = expl->next;
00685 
00686       }
00687 
00688     }
00689 
00690     sigl = sigl->next;
00691 
00692   }
00693 
00694   PROFILE_END;
00695 
00696 }

static void race_check_race_count (  )  [static]
Returns:
Returns TRUE if no race conditions were found or the user specified that we should continue to score the design.
Exceptions:
anonymous Throw

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

Referenced by race_check_modules().

00704                                     { PROFILE(RACE_CHECK_RACE_COUNT);
00705 
00706   /*
00707    If we were able to find race conditions and the user specified to check for race conditions
00708    and quit, display the number of race conditions found and return FALSE to cause everything to
00709    halt.
00710   */
00711   if( (races_found > 0) && (flag_race_check == FATAL) ) {
00712 
00713     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "%d race conditions were detected.  Exiting score command.", races_found );
00714     assert( rv < USER_MSG_LENGTH );
00715     print_output( user_msg, FATAL, __FILE__, __LINE__ );
00716     Throw 0;
00717 
00718   }
00719 
00720   PROFILE_END;
00721 
00722 }

void race_collect_lines ( func_unit funit,
int **  slines,
int **  elines,
int **  reasons,
int *  line_cnt 
)

Collects all of the lines in the specified module that were not verified due to race condition breach.

Collects all of the line numbers in the specified module that were ignored from coverage due to detecting a race condition. This function is primarily used by the GUI for outputting purposes.

Parameters:
funit Pointer to functional unit
slines Pointer to an array of starting line numbers that contain line numbers of race condition statements
elines Pointer to an array of ending line numbers that contain line numbers of race condition statements
reasons Pointer to an array of race condition reason integers, one for each line in the lines array
line_cnt Pointer to number of elements that exist in lines array

References race_blk_s::end_line, race_blk_s::next, PROFILE, PROFILE_END, func_unit_s::race_head, realloc_safe, race_blk_s::reason, and race_blk_s::start_line.

01056   { PROFILE(RACE_COLLECT_LINES);
01057 
01058   race_blk* curr_race = NULL;  /* Pointer to current race condition block */
01059 
01060   /* Begin by allocating some memory for the lines */
01061   *slines   = NULL;
01062   *elines   = NULL;
01063   *reasons  = NULL;
01064   *line_cnt = 0;
01065 
01066   curr_race = funit->race_head;
01067   while( curr_race != NULL ) {
01068 
01069     *slines  = (int*)realloc_safe( *slines,  (sizeof( int ) * (*line_cnt)), (sizeof( int ) * (*line_cnt + 1)) );
01070     *elines  = (int*)realloc_safe( *elines,  (sizeof( int ) * (*line_cnt)), (sizeof( int ) * (*line_cnt + 1)) );
01071     *reasons = (int*)realloc_safe( *reasons, (sizeof( int ) * (*line_cnt)), (sizeof( int ) * (*line_cnt + 1)) );
01072 
01073     (*slines)[*line_cnt]  = curr_race->start_line;
01074     (*elines)[*line_cnt]  = curr_race->end_line;
01075     (*reasons)[*line_cnt] = curr_race->reason;
01076     (*line_cnt)++;
01077 
01078     curr_race = curr_race->next;
01079 
01080   }
01081 
01082   PROFILE_END;
01083 
01084 }

void race_db_read ( char **  line,
func_unit curr_mod 
)

Reads contents from specified line for a race condition block and assigns the new block to the curr_mod.

Exceptions:
anonymous Throw Throw

Reads the specified line from the CDD file and parses it for race condition block information.

Parameters:
line Pointer to line containing information for a race condition block
curr_mod Pointer to current module to store race condition block to

References FATAL, race_blk_s::next, print_output(), PROFILE, PROFILE_END, race_blk_create(), func_unit_s::race_head, func_unit_s::race_tail, and Throw.

Referenced by db_read(), and funit_db_mod_merge().

00859   { PROFILE(RACE_DB_READ);
00860 
00861   int       start_line;     /* Starting line for race condition block */
00862   int       end_line;       /* Ending line for race condition block */
00863   int       reason;         /* Reason for why the race condition block exists */
00864   int       chars_read;     /* Number of characters read via sscanf */
00865   race_blk* rb;             /* Pointer to newly created race condition block */
00866 
00867   if( sscanf( *line, "%d %d %d%n", &reason, &start_line, &end_line, &chars_read ) == 3 ) {
00868 
00869     *line = *line + chars_read;
00870 
00871     if( curr_mod == NULL ) {
00872 
00873       print_output( "Internal error:  race condition in database written before its functional unit", FATAL, __FILE__, __LINE__ );
00874       Throw 0;
00875 
00876     } else {
00877 
00878       /* Create the new race condition block */
00879       rb = race_blk_create( reason, start_line, end_line );
00880 
00881       /* Add the new race condition block to the current module */
00882       if( curr_mod->race_head == NULL ) {
00883         curr_mod->race_head = curr_mod->race_tail = rb;
00884       } else {
00885         curr_mod->race_tail->next = rb;
00886         curr_mod->race_tail       = rb;
00887       }
00888 
00889     }
00890 
00891   } else {
00892 
00893     print_output( "Unable to parse race condition line in database file.  Unable to read.", FATAL, __FILE__, __LINE__ );
00894     Throw 0;
00895 
00896   }
00897 
00898   PROFILE_END;
00899 
00900 }

void race_db_write ( race_blk rb,
FILE *  file 
)

Writes contents of specified race condition block to specified file output.

Writes contents of specified race condition block to the specified output stream.

Parameters:
rb Pointer to race condition block to write to specified output file
file File handle of output stream to write

References DB_TYPE_RACE, race_blk_s::end_line, PROFILE, PROFILE_END, race_blk_s::reason, and race_blk_s::start_line.

Referenced by funit_db_write().

00837   { PROFILE(RACE_DB_WRITE);
00838 
00839   fprintf( file, "%d %d %d %d\n",
00840     DB_TYPE_RACE,
00841     rb->reason,
00842     rb->start_line,
00843     rb->end_line
00844   );
00845 
00846   PROFILE_END;
00847 
00848 }

static int race_find_head_statement ( statement stmt  )  [static]
Returns:
Returns index of found head statement in statement block array if found; otherwise, returns a value of -1 to indicate that no such statement block exists.
Parameters:
stmt Pointer to statement to search for in statement block array

References PROFILE, PROFILE_END, and sb_size.

Referenced by race_check_one_block_assignment(), and race_handle_race_condition().

00236   { PROFILE(RACE_FIND_HEAD_STATEMENT);
00237 
00238   int i = 0;   /* Loop iterator */
00239 
00240   while( (i < sb_size) && (sb[i].stmt != stmt) ) {
00241     i++;
00242   }
00243 
00244   PROFILE_END;
00245 
00246   return( (i == sb_size) ? -1 : i );
00247 
00248 }

static statement* race_find_head_statement_containing_statement ( statement stmt  )  [static]
Returns:
Returns a pointer to the statement block containing the given statement (if one is found); otherwise, returns a value of NULL.

Searches all statement blocks for one that contains the given statement within it. Once it is found, a pointer to the head statement block is returned to the calling function. If it is not found, a value of NULL is returned, indicating that the statement block could not be found for the given statement.

Parameters:
stmt Pointer to statement to search for matching statement block

References PROFILE, PROFILE_END, race_find_head_statement_containing_statement_helper(), sb_size, and stmt_conn_id.

Referenced by race_get_head_statement().

00186   { PROFILE(RACE_FIND_HEAD_STATEMENT_CONTAINING_STATEMENT);
00187 
00188   int i = 0;   /* Loop iterator */
00189 
00190   while( (i < sb_size) && !race_find_head_statement_containing_statement_helper( sb[i].stmt, stmt ) ) {
00191     i++;
00192     stmt_conn_id++;
00193   }
00194 
00195   if( i < sb_size ) {
00196     stmt_conn_id++;
00197   }
00198 
00199   PROFILE_END;
00200 
00201   return( (i == sb_size) ? NULL : sb[i].stmt );
00202 
00203 }

static bool race_find_head_statement_containing_statement_helper ( statement curr,
statement to_find 
) [static]
Returns:
Returns TRUE if the specified to_find statement was found in the statement block specified by curr; otherwise, returns FALSE.

Recursively iterates through specified statement block, searching for statement pointed to by to_find. If the statement is found, a value of TRUE is returned to the calling function; otherwise, a value of FALSE is returned.

Parameters:
curr Pointer to current statement to check
to_find Pointer to statement to find

References statement_s::conn_id, expression_s::elem, statement_s::exp, EXP_OP_FORK, EXP_OP_NB_CALL, EXP_OP_TASK_CALL, FALSE, func_unit_s::first_stmt, expression_s::funit, statement_s::next_false, statement_s::next_true, expression_s::op, statement_s::part, PROFILE, PROFILE_END, stmt_conn_id, statement_s::suppl, and TRUE.

Referenced by race_find_head_statement_containing_statement().

00134   { PROFILE(RACE_FIND_HEAD_STATEMENT_CONTAINING_STATEMENT_HELPER);
00135 
00136   bool retval = FALSE;  /* Return value for this function */
00137 
00138   if( (curr != NULL) && (curr->conn_id != stmt_conn_id) ) {
00139 
00140     curr->conn_id = stmt_conn_id;
00141 
00142     if( curr == to_find ) {
00143 
00144       retval = TRUE;
00145 
00146     } else {
00147 
00148       /* 
00149        If the current statement is a named block call, task call or fork statement, look for specified
00150        statement in its statement block.
00151       */
00152       if( (curr->exp->op == EXP_OP_NB_CALL)   ||
00153           (curr->exp->op == EXP_OP_TASK_CALL) ||
00154           (curr->exp->op == EXP_OP_FORK) ) {
00155         retval = race_find_head_statement_containing_statement_helper( curr->exp->elem.funit->first_stmt, to_find );
00156       }
00157 
00158       if( !retval && (curr->suppl.part.stop_true == 0) ) {
00159         retval = race_find_head_statement_containing_statement_helper( curr->next_true, to_find );
00160       }
00161    
00162       if( !retval && (curr->suppl.part.stop_false == 0) && (curr->next_true != curr->next_false) ) {
00163         retval = race_find_head_statement_containing_statement_helper( curr->next_false, to_find );
00164       }
00165 
00166     }
00167 
00168   }
00169 
00170   PROFILE_END;
00171 
00172   return( retval );
00173 
00174 }

static statement* race_get_head_statement ( expression expr  )  [static]
Returns:
Returns pointer to head statement of statement block containing the specified expression

Finds the head statement of the statement block containing the expression specified in the parameter list. Verifies that the return value is never NULL (this would be an internal error if it existed).

Parameters:
expr Pointer to root expression to find in statement list

References expression_get_root_statement(), PROFILE, PROFILE_END, and race_find_head_statement_containing_statement().

Referenced by race_check_one_block_assignment().

00213   { PROFILE(RACE_GET_HEAD_STATEMENT);
00214 
00215   statement* curr_stmt;  /* Pointer to current statement containing the expression */
00216 
00217   /* First, find the statement associated with this expression */
00218   if( (curr_stmt = expression_get_root_statement( expr )) != NULL ) {
00219 
00220     curr_stmt = race_find_head_statement_containing_statement( curr_stmt );
00221 
00222   }
00223 
00224   PROFILE_END;
00225 
00226   return( curr_stmt );
00227 
00228 }

void race_get_stats ( race_blk curr,
unsigned int *  race_total,
unsigned int  type_total[][RACE_TYPE_NUM] 
)

Get statistic information for the specified race condition block list.

Iterates through specified race condition block list, totaling the number of race conditions found as well as tallying each type of race condition.

Parameters:
curr Pointer to head of race condition block list
race_total Pointer to value that will hold the total number of race conditions in this module
type_total Pointer to array containing number of race conditions found for each violation type

References race_blk_s::next, PROFILE, PROFILE_END, and race_blk_s::reason.

Referenced by report_gather_funit_stats(), and report_gather_instance_stats().

00910   { PROFILE(RACE_GET_STATS);
00911 
00912   int i;  /* Loop iterator */
00913 
00914   /* Clear totals */
00915   *race_total = 0;
00916   for( i=0; i<RACE_TYPE_NUM; i++ ) {
00917     (*type_total)[i] = 0;
00918   }
00919 
00920   /* Tally totals */
00921   while( curr != NULL ) {
00922     (*type_total)[curr->reason]++;
00923     (*race_total)++;
00924     curr = curr->next;
00925   }
00926 
00927   PROFILE_END;
00928 
00929 }

static void race_handle_race_condition ( expression expr,
func_unit mod,
statement stmt,
statement base,
int  reason 
) [static]

Outputs necessary information to user regarding the race condition that was detected and performs any necessary memory cleanup to remove the statement block involved in the race condition.

Parameters:
expr Pointer to expression containing signal that was found to be in a race condition
mod Pointer to module containing detected race condition
stmt Pointer to expr's head statement
base Pointer to head statement block that was found to be in conflict with stmt
reason Specifies what type of race condition was being checked that failed

References race_blk_s::end_line, statement_s::exp, func_unit_s::filename, flag_race_check, expression_s::line, race_blk_s::next, NORMAL, obf_file, print_output(), PROFILE, PROFILE_END, race_blk_create(), race_find_head_statement(), func_unit_s::race_head, race_msgs, func_unit_s::race_tail, races_found, stmt_blk_s::remove, race_blk_s::start_line, statement_get_last_line(), TRUE, user_msg, USER_MSG_LENGTH, WARNING, and WARNING_WRAP.

Referenced by race_check_assignment_types(), and race_check_one_block_assignment().

00344   { PROFILE(RACE_HANDLE_RACE_CONDITION);
00345 
00346   race_blk*    rb;         /* Pointer to race condition block to add to specified module */
00347   int          i;          /* Loop iterator */
00348   int          last_line;  /* Holds the line number of the last line in the specified statement */
00349   unsigned int rv;         /* Return value from snprintf calls */
00350 
00351   /* If the base pointer is NULL, the stmt refers to a statement block that conflicts with an input port */
00352   if( base == NULL ) {
00353 
00354     if( flag_race_check != NORMAL ) {
00355 
00356       print_output( "", (flag_race_check + 1), __FILE__, __LINE__ );
00357       rv = snprintf( user_msg, USER_MSG_LENGTH, "Possible race condition detected - %s", race_msgs[reason] );
00358       assert( rv < USER_MSG_LENGTH );
00359       print_output( user_msg, flag_race_check, __FILE__, __LINE__ );
00360       rv = snprintf( user_msg, USER_MSG_LENGTH, "  Signal assigned in file: %s, line: %d", obf_file( mod->filename ), expr->line );
00361       assert( rv < USER_MSG_LENGTH );
00362       print_output( user_msg, (flag_race_check + 1), __FILE__, __LINE__ );
00363 
00364       if( flag_race_check == WARNING ) {
00365         print_output( "  * Safely removing statement block from coverage consideration", WARNING_WRAP, __FILE__, __LINE__ );
00366         rv = snprintf( user_msg, USER_MSG_LENGTH, "    Statement block starting at file: %s, line: %d",
00367                        obf_file( mod->filename ), stmt->exp->line );
00368         assert( rv < USER_MSG_LENGTH );
00369         print_output( user_msg, WARNING_WRAP, __FILE__, __LINE__ );
00370       }
00371               
00372     }
00373 
00374   /* If the stmt and base pointers are pointing to different statements, we will output conflict for stmt */
00375   } else if( stmt != base ) { 
00376 
00377     if( flag_race_check != NORMAL ) {
00378 
00379       print_output( "", (flag_race_check + 1), __FILE__, __LINE__ );
00380       rv = snprintf( user_msg, USER_MSG_LENGTH, "Possible race condition detected - %s", race_msgs[reason] );
00381       assert( rv < USER_MSG_LENGTH );
00382       print_output( user_msg, flag_race_check, __FILE__, __LINE__ );
00383       rv = snprintf( user_msg, USER_MSG_LENGTH, "  Signal assigned in file: %s, line: %d", obf_file( mod->filename ), expr->line );
00384       assert( rv < USER_MSG_LENGTH );
00385       print_output( user_msg, (flag_race_check + 1), __FILE__, __LINE__ );
00386       rv = snprintf( user_msg, USER_MSG_LENGTH, "  Signal also assigned in statement starting at file: %s, line: %d",
00387                      obf_file( mod->filename ), base->exp->line );
00388       assert( rv < USER_MSG_LENGTH );
00389       print_output( user_msg, (flag_race_check + 1), __FILE__, __LINE__ );
00390 
00391       if( flag_race_check == WARNING ) {
00392         print_output( "  * Safely removing statement block from coverage consideration", WARNING_WRAP, __FILE__, __LINE__ );
00393         rv = snprintf( user_msg, USER_MSG_LENGTH, "    Statement block starting at file: %s, line: %d",
00394                        obf_file( mod->filename ), stmt->exp->line );
00395         assert( rv < USER_MSG_LENGTH );
00396         print_output( user_msg, WARNING_WRAP, __FILE__, __LINE__ );
00397       }
00398 
00399     }
00400 
00401   /* If stmt and base are pointing to the same statement, just report that we are removing the base statement */
00402   } else {
00403 
00404     if( flag_race_check != NORMAL ) {
00405 
00406       if( reason != 6 ) {
00407         
00408         print_output( "", (flag_race_check + 1), __FILE__, __LINE__ );
00409         rv = snprintf( user_msg, USER_MSG_LENGTH, "Possible race condition detected - %s", race_msgs[reason] );
00410         assert( rv < USER_MSG_LENGTH );
00411         print_output( user_msg, flag_race_check, __FILE__, __LINE__ );
00412         rv = snprintf( user_msg, USER_MSG_LENGTH, "  Statement block starting in file: %s, line: %d",
00413                        obf_file( mod->filename ), stmt->exp->line );
00414         assert( rv < USER_MSG_LENGTH );
00415         print_output( user_msg, (flag_race_check + 1), __FILE__, __LINE__ );
00416         if( flag_race_check == WARNING ) {
00417           print_output( "  * Safely removing statement block from coverage consideration", WARNING_WRAP, __FILE__, __LINE__ );
00418         }
00419 
00420       } else {
00421 
00422         if( flag_race_check == WARNING ) {
00423           print_output( "", WARNING_WRAP, __FILE__, __LINE__ );
00424           print_output( "* Safely removing statement block from coverage consideration", WARNING, __FILE__, __LINE__ );
00425           rv = snprintf( user_msg, USER_MSG_LENGTH, "  Statement block starting at file: %s, line: %d",
00426                          obf_file( mod->filename ), stmt->exp->line );
00427           assert( rv < USER_MSG_LENGTH );
00428           print_output( user_msg, WARNING_WRAP, __FILE__, __LINE__ );
00429         }
00430 
00431       }
00432 
00433     }
00434 
00435   }
00436 
00437   /* Calculate the last line of this statement so that we are not constantly doing it */
00438   last_line = statement_get_last_line( stmt );
00439 
00440   /* Search this module's race list to see if this statement block already exists */
00441   rb = mod->race_head;
00442   while( (rb != NULL) && (rb->start_line != stmt->exp->line) && (rb->end_line != last_line) ) {
00443     rb = rb->next;
00444   }  
00445 
00446   /* If a matching statement block was not found, go ahead and create it */
00447   if( rb == NULL ) {
00448 
00449     /* Create a race condition block and add it to current module */
00450     rb = race_blk_create( reason, stmt->exp->line, last_line );
00451 
00452     /* Add the newly created race condition block to the current module */
00453     if( mod->race_head == NULL ) {
00454       mod->race_head = mod->race_tail = rb;
00455     } else {
00456       mod->race_tail->next = rb;
00457       mod->race_tail       = rb;
00458     }
00459 
00460   }
00461 
00462   /* Set remove flag in stmt_blk array to remove this module from memory */
00463   i = race_find_head_statement( stmt );
00464   assert( i != -1 );
00465   sb[i].remove = TRUE;
00466 
00467   /* Increment races found flag */
00468   races_found++;
00469 
00470   PROFILE_END;
00471 
00472 }

void race_report ( FILE *  ofile,
bool  verbose 
)

Displays report information for race condition blocks in design.

Generates the race condition report information and displays it to the specified output stream.

Parameters:
ofile Output stream to display report information to
verbose Specifies if summary or verbose output should be displayed

References curr_db, funit_head, PROFILE, PROFILE_END, race_report_summary(), and race_report_verbose().

Referenced by report_generate().

01023   { PROFILE(RACE_REPORT);
01024 
01025   bool found;  /* If set to TRUE, race conditions were found */
01026 
01027   fprintf( ofile, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
01028   fprintf( ofile, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   RACE CONDITION VIOLATIONS   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
01029   fprintf( ofile, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
01030   fprintf( ofile, "Module                    Filename                 Number of Violations found\n" );
01031   fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
01032 
01033   found = race_report_summary( ofile, db_list[curr_db]->funit_head );
01034 
01035   if( verbose && found ) {
01036     fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
01037     race_report_verbose( ofile, db_list[curr_db]->funit_head );
01038   }
01039 
01040   fprintf( ofile, "\n\n" );
01041 
01042   PROFILE_END;
01043 
01044 }

static bool race_report_summary ( FILE *  ofile,
funit_link head 
) [static]
Returns:
Returns TRUE if any race conditions were found in the functional unit list

Displays the summary report for race conditions for all functional units in design.

Parameters:
ofile Pointer to output file to use
head Pointer to head of functional unit list to report

References FALSE, func_unit_s::filename, funit_link_s::funit, funit_flatten_name(), FUNIT_MODULE, get_basename(), funit_link_s::next, obf_file, PROFILE, PROFILE_END, statistic_s::race_total, func_unit_s::stat, TRUE, and func_unit_s::type.

Referenced by race_report().

00939   { PROFILE(RACE_REPORT_SUMMARY);
00940 
00941   bool found = FALSE;  /* Return value for this function */
00942 
00943   while( head != NULL ) {
00944 
00945     if( (head->funit->type == FUNIT_MODULE) && (head->funit->stat != NULL) ) {
00946 
00947       found = (head->funit->stat->race_total > 0) ? TRUE : found;
00948 
00949       fprintf( ofile, "  %-20.20s    %-20.20s        %u\n", 
00950                funit_flatten_name( head->funit ),
00951                get_basename( obf_file( head->funit->filename ) ),
00952                head->funit->stat->race_total );
00953 
00954     }
00955 
00956     head = head->next;
00957 
00958   }
00959 
00960   PROFILE_END;
00961 
00962   return( found );
00963 
00964 }

static void race_report_verbose ( FILE *  ofile,
funit_link head 
) [static]

Outputs a verbose race condition report to the specified output file specifying the line number and race condition reason for all functional units in the design.

Parameters:
ofile Pointer to output file to use
head Pointer to head of functional unit list being reported

References func_unit_s::filename, funit_link_s::funit, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, funit_flatten_name(), FUNIT_FUNCTION, FUNIT_MODULE, FUNIT_NAMED_BLOCK, FUNIT_TASK, funit_link_s::next, race_blk_s::next, obf_file, obf_funit, PROFILE, PROFILE_END, func_unit_s::race_head, race_msgs, statistic_s::race_total, race_blk_s::reason, race_blk_s::start_line, func_unit_s::stat, and func_unit_s::type.

Referenced by race_report().

00973   { PROFILE(RACE_REPORT_VERBOSE);
00974 
00975   race_blk* curr_race;  /* Pointer to current race condition block */
00976 
00977   while( head != NULL ) {
00978 
00979     if( (head->funit->stat != NULL) && (head->funit->stat->race_total > 0) ) {
00980 
00981       fprintf( ofile, "\n" );
00982       switch( head->funit->type ) {
00983         case FUNIT_MODULE       :  fprintf( ofile, "    Module: " );       break;
00984         case FUNIT_ANAMED_BLOCK :
00985         case FUNIT_NAMED_BLOCK  :  fprintf( ofile, "    Named Block: " );  break;
00986         case FUNIT_AFUNCTION    :
00987         case FUNIT_FUNCTION     :  fprintf( ofile, "    Function: " );     break;
00988         case FUNIT_ATASK        :
00989         case FUNIT_TASK         :  fprintf( ofile, "    Task: " );         break;
00990         default                 :  fprintf( ofile, "    UNKNOWN: " );      break;
00991       }
00992       fprintf( ofile, "%s, File: %s\n", obf_funit( funit_flatten_name( head->funit ) ), obf_file( head->funit->filename ) );
00993       fprintf( ofile, "    -------------------------------------------------------------------------------------------------------------\n" );
00994 
00995       fprintf( ofile, "      Starting Line #     Race Condition Violation Reason\n" );
00996       fprintf( ofile, "      ---------------------------------------------------------------------------------------------------------\n" );
00997 
00998       curr_race = head->funit->race_head;
00999       while( curr_race != NULL ) {
01000         fprintf( ofile, "              %7d:    %s\n", curr_race->start_line, race_msgs[curr_race->reason] );
01001         curr_race = curr_race->next;
01002       }
01003 
01004       fprintf( ofile, "\n" );
01005 
01006     }
01007 
01008     head = head->next;
01009                                                                                                
01010   }
01011 
01012   PROFILE_END;
01013 
01014 }


Variable Documentation

unsigned int curr_db

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

Pointer to the functional unit structure for the functional unit that is currently being parsed.

Array of database pointers storing all currently loaded databases.

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

Specifies how race conditions should be handled

Referenced by race_check_race_count(), race_handle_race_condition(), and score_parse_args().

Informational line for the CDD file.

Pointer to head of string list containing the names of modules that should be ignored for race condition checking.

Pointer to tail of string list containing the names of modules that should be ignored for race condition checking.

const char* race_msgs[RACE_TYPE_NUM]
Initial value:
 {
  "Sequential statement block contains blocking assignment(s)",
  "Combinational statement block contains non-blocking assignment(s)",
  "Mixed statement block contains blocking assignment(s)",
  "Statement block contains both blocking and non-blocking assignment(s)", 
  "Signal assigned in two different statement blocks",
  "Signal assigned both in statement block and via input/inout port",
  "System call $strobe used to output signal assigned via blocking assignment",
  "Procedural assignment with #0 delay performed"
}

This array is used to output the various race condition violation messages in both the parsing and report functions

Referenced by race_handle_race_condition(), and race_report_verbose().

int races_found = 0 [static]

Tracks the number of race conditions that were detected during the race-condition checking portion of the scoring command.

Referenced by race_check_race_count(), and race_handle_race_condition().

stmt_blk* sb = NULL [static]

Pointer to array of statement blocks for the specified design.

int sb_size [static]

Specifies current connection ID to use for connecting statements. This value should be passed to the statement_connect function and incremented immediately after.

Referenced by db_statement_connect(), race_calc_assignments(), race_check_modules(), race_find_head_statement_containing_statement(), and race_find_head_statement_containing_statement_helper().

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