#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_blk * | race_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 statement * | race_find_head_statement_containing_statement (statement *stmt) |
static statement * | race_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_blk * | sb = 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_unit * | curr_funit |
isuppl | info_suppl |
int | stmt_conn_id |
bool | debug_mode |
str_link * | race_ignore_mod_head |
str_link * | race_ignore_mod_tail |
static race_blk* race_blk_create | ( | int | reason, | |
int | start_line, | |||
int | end_line | |||
) | [static] |
Allocates and initializes memory for a race condition block.
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.
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.
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.
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.
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.
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.
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.
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] |
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.
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.
anonymous | Throw Throw |
Reads the specified line from the CDD file and parses it for race condition block information.
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.
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] |
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 }
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.
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] |
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.
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] |
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).
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.
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.
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.
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] |
Displays the summary report for race conditions for all functional units in design.
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.
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 }
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.
If set to TRUE, causes debug information to be spewed to screen.
int flag_race_check |
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] |
{ "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().
int sb_size [static] |
Number of entries loaded in the sb array.
Referenced by race_check_assignment_types(), race_check_modules(), race_find_head_statement(), and race_find_head_statement_containing_statement().
int stmt_conn_id |
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.