Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

/Users/trevorw/projects/release/covered-0.7.4/src/expr.h File Reference


Detailed Description

Contains functions for handling expressions.

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
12/1/2001

#include <stdio.h>
#include "defines.h"

Go to the source code of this file.

Functions

void expression_create_nba (expression *expr, vsignal *lhs_sig, vector *rhs_vec)
 Creates, initializes and adds a non-blocking assignment structure to the given expression's element pointer.

expressionexpression_is_nba_lhs (expression *exp)
 Returns a pointer to the non-blocking assignment expression if the given expression is an assignable expression on the LHS of a non-blocking assignment.

expressionexpression_create (expression *right, expression *left, exp_op_type op, bool lhs, int id, int line, unsigned int first, unsigned int last, bool data)
 Creates new expression.

void expression_set_value (expression *exp, vsignal *sig, func_unit *funit)
 Sets the specified expression value to the specified vector value.

void expression_set_signed (expression *exp)
 Sets the signed bit for all appropriate parent expressions.

void expression_resize (expression *expr, func_unit *funit, bool recursive, bool alloc)
 Recursively resizes specified expression tree leaf node.

int expression_get_id (expression *expr, bool parse_mode)
 Returns expression ID of this expression.

expressionexpression_get_first_line_expr (expression *expr)
 Returns first line in this expression tree.

expressionexpression_get_last_line_expr (expression *expr)
 Returns last line in this expression tree.

unsigned int expression_get_curr_dimension (expression *expr)
 Returns the current dimension of the given expression.

void expression_find_rhs_sigs (expression *expr, str_link **head, str_link **tail)
 Finds all RHS signals in given expression tree.

expressionexpression_find_uline_id (expression *expr, int ulid)
 Finds the expression in this expression tree with the specified underline id.

bool expression_find_expr (expression *root, expression *expr)
 Returns TRUE if the specified expression exists within the given root expression tree.

bool expression_contains_expr_calling_stmt (expression *expr, statement *stmt)
 Searches for an expression that calls the given statement.

statementexpression_get_root_statement (expression *exp)
 Finds the root statement for the given expression.

void expression_assign_expr_ids (expression *root, func_unit *funit)
 Assigns each expression in the given tree a unique identifier.

void expression_db_write (expression *expr, FILE *file, bool parse_mode, bool ids_issued)
 Writes this expression to the specified database file.

void expression_db_write_tree (expression *root, FILE *file)
 Writes the entire expression tree to the specified data file.

void expression_db_read (char **line, func_unit *curr_mod, bool eval)
 Reads current line of specified file and parses for expression information.

void expression_db_merge (expression *base, char **line, bool same)
 Reads and merges two expressions and stores result in base expression.

void expression_merge (expression *base, expression *other)
 Merges two expressions into the base expression.

const char * expression_string_op (int op)
 Returns user-readable name of specified expression operation.

char * expression_string (expression *exp)
 Returns user-readable version of the supplied expression.

void expression_display (expression *expr)
 Displays the specified expression information.

bool expression_operate (expression *expr, thread *thr, const sim_time *time)
 Performs operation specified by parameter expression.

void expression_operate_recursively (expression *expr, func_unit *funit, bool sizing)
 Performs recursive expression operation (parse mode only).

bool expression_is_static_only (expression *expr)
 Returns TRUE if specified expression is found to contain all static leaf expressions.

bool expression_is_bit_select (expression *expr)
 Returns TRUE if specified expression is a part of an bit select expression tree.

bool expression_is_in_rassign (expression *expr)
 Returns TRUE if specified expression is in an RASSIGN expression tree.

bool expression_is_last_select (expression *expr)
 Returns TRUE if specified expression is the last select of a signal.

void expression_set_assigned (expression *expr)
 Sets the expression signal supplemental field assigned bit if the given expression is an RHS of an assignment.

void expression_set_changed (expression *expr)
 Sets the left/right changed expression bits for each expression in the tree.

void expression_dealloc (expression *expr, bool exp_only)
 Deallocates memory used for expression.


Function Documentation

void expression_assign_expr_ids expression root,
func_unit funit
 

Assigns each expression in the given tree a unique identifier.

Exceptions:
anonymous expression_resize expression_assign_expr_ids expression_assign_expr_ids
Recursively iterates down the specified expression tree assigning unique IDs to each expression.
Parameters:
root  Pointer to root of the expression tree to assign unique IDs for
funit  Pointer to functional unit containing this expression tree

01481   { PROFILE(EXPRESSION_ASSIGN_EXPR_IDS);
01482 
01483   if( root != NULL ) {
01484 
01485     /* Traverse children first */
01486     expression_assign_expr_ids( root->left, funit );
01487     expression_assign_expr_ids( root->right, funit );
01488 
01489     /* Assign our expression a unique ID value */
01490     root->ulid = curr_expr_id;
01491     curr_expr_id++;
01492 
01493     /* Resize ourselves */
01494     expression_resize( root, funit, FALSE, FALSE );
01495 
01496   }
01497 
01498   PROFILE_END;
01499 
01500 }

bool expression_contains_expr_calling_stmt expression expr,
statement stmt
 

Searches for an expression that calls the given statement.

Returns:
Returns TRUE if the given expression tree contains an expression that calls the given statement.
Parameters:
expr  Pointer to root of expression tree to search
stmt  Pointer to statement to search for

01432   { PROFILE(EXPRESSION_CONTAINS_EXPR_CALLING_STMT);
01433 
01434   bool retval = (expr != NULL) &&
01435                 (((ESUPPL_TYPE( expr->suppl ) == ETYPE_FUNIT) && (expr->elem.funit->first_stmt == stmt)) ||
01436                  expression_contains_expr_calling_stmt( expr->left, stmt ) ||
01437                  expression_contains_expr_calling_stmt( expr->right, stmt ));
01438 
01439   PROFILE_END;
01440 
01441   return( retval );
01442 
01443 }

expression* expression_create expression right,
expression left,
exp_op_type  op,
bool  lhs,
int  id,
int  line,
unsigned int  first,
unsigned int  last,
bool  data
 

Creates new expression.

Returns:
Returns pointer to newly created expression.
Exceptions:
anonymous Throw expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value
Creates a new expression from heap memory and initializes its values for usage. Right and left expressions need to be created before this function is called.
Parameters:
right  Pointer to expression on right
left  Pointer to expression on left
op  Operation to perform for this expression
lhs  Specifies this expression is a left-hand-side assignment expression
id  ID for this expression as determined by the parent
line  Line number this expression is on
first  First column index of expression
last  Last column index of expression
data  Specifies if we should create a uint8 array for the vector value

00634   { PROFILE(EXPRESSION_CREATE);
00635 
00636   expression* new_expr;    /* Pointer to newly created expression */
00637   int         rwidth = 0;  /* Bit width of expression on right */
00638   int         lwidth = 0;  /* Bit width of expression on left */
00639 
00640   new_expr = (expression*)malloc_safe( sizeof( expression ) );
00641 
00642   new_expr->suppl.all           = 0;
00643   new_expr->suppl.part.lhs      = (uint8)lhs & 0x1;
00644   new_expr->suppl.part.gen_expr = (generate_expr_mode > 0) ? 1 : 0;
00645   new_expr->suppl.part.root     = 1;
00646   new_expr->op                  = op;
00647   new_expr->id                  = id;
00648   new_expr->ulid                = -1;
00649   new_expr->line                = line;
00650   new_expr->col                 = ((first & 0xffff) << 16) | (last & 0xffff);
00651   new_expr->exec_num            = 0;
00652   new_expr->sig                 = NULL;
00653   new_expr->parent              = (expr_stmt*)malloc_safe( sizeof( expr_stmt ) );
00654   new_expr->parent->expr        = NULL;
00655   new_expr->right               = right;
00656   new_expr->left                = left;
00657   new_expr->value               = (vector*)malloc_safe( sizeof( vector ) );
00658   new_expr->suppl.part.owns_vec = 1;
00659   new_expr->value->value.ul     = NULL;
00660   new_expr->value->suppl.all    = 0;
00661   new_expr->table               = NULL;
00662   new_expr->elem.funit          = NULL;
00663   new_expr->name                = NULL;
00664 
00665   if( EXPR_OP_HAS_DIM( op ) ) {
00666     new_expr->elem.dim           = (exp_dim*)malloc_safe( sizeof( exp_dim ) );
00667     new_expr->elem.dim->curr_lsb = -1;
00668   }
00669 
00670   if( right != NULL ) {
00671 
00672     /* Get information from right */
00673     assert( right->value != NULL );
00674     rwidth = right->value->width;
00675 
00676     /* Set right expression parent to this expression */
00677     assert( right->parent->expr == NULL );
00678     right->parent->expr = new_expr;
00679 
00680     /* Reset root bit of right expression */
00681     right->suppl.part.root = 0;
00682 
00683   }
00684 
00685   if( left != NULL ) {
00686 
00687     /* Get information from left */
00688     assert( left->value != NULL );
00689     lwidth = left->value->width;
00690 
00691     /* Set left expression parent to this expression (if this is not a case expression) */
00692     if( (op != EXP_OP_CASE) && (op != EXP_OP_CASEX) && (op != EXP_OP_CASEZ) ) {
00693       assert( left->parent->expr == NULL );
00694       left->parent->expr    = new_expr;
00695       left->suppl.part.root = 0;
00696     }
00697 
00698   }
00699 
00700   Try {
00701 
00702     /* Create value vector */
00703     if( ((op == EXP_OP_MULTIPLY) || (op == EXP_OP_LIST)) && (rwidth > 0) && (lwidth > 0) ) {
00704 
00705       /* For multiplication, we need a width the sum of the left and right expressions */
00706       expression_create_value( new_expr, (lwidth + rwidth), data );
00707 
00708     } else if( (op == EXP_OP_CONCAT) && (rwidth > 0) ) {
00709 
00710       expression_create_value( new_expr, rwidth, data );
00711 
00712     } else if( (op == EXP_OP_EXPAND) && (rwidth > 0) && (lwidth > 0) && (left->value->value.ul != NULL) ) {
00713 
00714       /*
00715        If the left-hand expression is a known value, go ahead and create the value here; otherwise,
00716        hold off because our vector value will be coming.
00717       */
00718       if( !vector_is_unknown( left->value ) ) {
00719         expression_create_value( new_expr, (vector_to_int( left->value ) * rwidth), data );
00720       } else {
00721         expression_create_value( new_expr, 1, data );
00722       }
00723 
00724     /* $time, $realtobits, $bitstoreal, $itor and $rtoi expressions are always 64-bits wide */
00725     } else if( (op == EXP_OP_STIME) || (op == EXP_OP_SR2B) || (op == EXP_OP_SB2R) || (op == EXP_OP_SI2R) || (op == EXP_OP_SR2I) ) {
00726 
00727       expression_create_value( new_expr, 64, data );
00728 
00729     /* $random, $urandom, $urandom_range, $shortrealtobits and $bitstoshortreal expressions are always 32-bits wide */
00730     } else if( (op == EXP_OP_SRANDOM) || (op == EXP_OP_SURANDOM) || (op == EXP_OP_SURAND_RANGE) || (op == EXP_OP_SSR2B) || (op == EXP_OP_SB2SR) ) {
00731 
00732       expression_create_value( new_expr, 32, data );
00733 
00734     } else if( (op == EXP_OP_LT)        ||
00735                (op == EXP_OP_GT)        ||
00736                (op == EXP_OP_EQ)        ||
00737                (op == EXP_OP_CEQ)       ||
00738                (op == EXP_OP_LE)        ||
00739                (op == EXP_OP_GE)        ||
00740                (op == EXP_OP_NE)        ||
00741                (op == EXP_OP_CNE)       ||
00742                (op == EXP_OP_LOR)       ||
00743                (op == EXP_OP_LAND)      ||
00744                (op == EXP_OP_UAND)      ||
00745                (op == EXP_OP_UNOT)      ||
00746                (op == EXP_OP_UOR)       ||
00747                (op == EXP_OP_UXOR)      ||
00748                (op == EXP_OP_UNAND)     ||
00749                (op == EXP_OP_UNOR)      ||
00750                (op == EXP_OP_UNXOR)     ||
00751                (op == EXP_OP_EOR)       ||
00752                (op == EXP_OP_NEDGE)     ||
00753                (op == EXP_OP_PEDGE)     ||
00754                (op == EXP_OP_AEDGE)     ||
00755                (op == EXP_OP_CASE)      ||
00756                (op == EXP_OP_CASEX)     ||
00757                (op == EXP_OP_CASEZ)     ||
00758                (op == EXP_OP_DEFAULT)   ||
00759                (op == EXP_OP_REPEAT)    ||
00760                (op == EXP_OP_RPT_DLY)   ||
00761                (op == EXP_OP_WAIT)      ||
00762                (op == EXP_OP_SFINISH)   ||
00763                (op == EXP_OP_SSTOP)     ||
00764                (op == EXP_OP_SSRANDOM)  ||
00765                (op == EXP_OP_STESTARGS) ||
00766                (op == EXP_OP_SVALARGS) ) {
00767   
00768       /* If this expression will evaluate to a single bit, create vector now */
00769       expression_create_value( new_expr, 1, data );
00770 
00771     } else {
00772 
00773       /* If both right and left values have their width values set. */
00774       if( (rwidth > 0) && (lwidth > 0) && 
00775           (op != EXP_OP_MBIT_SEL)       &&
00776           (op != EXP_OP_MBIT_POS)       &&
00777           (op != EXP_OP_MBIT_NEG)       &&
00778           (op != EXP_OP_PARAM_MBIT)     &&
00779           (op != EXP_OP_PARAM_MBIT_POS) &&
00780           (op != EXP_OP_PARAM_MBIT_NEG) ) {
00781 
00782         if( rwidth >= lwidth ) {
00783           /* Check to make sure that nothing has gone drastically wrong */
00784           expression_create_value( new_expr, rwidth, data );
00785         } else {
00786           /* Check to make sure that nothing has gone drastically wrong */
00787           expression_create_value( new_expr, lwidth, data );
00788         }
00789 
00790       } else {
00791  
00792         expression_create_value( new_expr, 0, FALSE );
00793  
00794       }
00795 
00796     }
00797 
00798   } Catch_anonymous {
00799     expression_dealloc( new_expr, TRUE );
00800     Throw 0;
00801   }
00802 
00803 /*
00804   if( (data == FALSE) && (generate_expr_mode == 0) ) {
00805     assert( new_expr->value->value.ul == NULL );
00806   }
00807 */
00808 
00809   PROFILE_END;
00810 
00811   return( new_expr );
00812 
00813 }

void expression_create_nba expression expr,
vsignal lhs_sig,
vector rhs_vec
 

Creates, initializes and adds a non-blocking assignment structure to the given expression's element pointer.

Allocates a non-blocking assignment structure to the given expression and initializes it.

Parameters:
expr  Pointer to expression to add non-blocking assignment structure to
lhs_sig  Pointer to left-hand-side signal
rhs_vec  Pointer to right-hand-side vector

00492   { PROFILE(EXPRESSION_CREATE_NBA);
00493 
00494   exp_dim* dim = expr->elem.dim;
00495 
00496   /* Allocate memory */
00497   nonblock_assign* nba = (nonblock_assign*)malloc_safe( sizeof( nonblock_assign ) );
00498 
00499   /* Initialize the structure */
00500   nba->lhs_sig         = lhs_sig;
00501   nba->rhs_vec         = rhs_vec;
00502   nba->suppl.is_signed = (expr->op == EXP_OP_SIG) ? rhs_vec->suppl.part.is_signed : FALSE;
00503   nba->suppl.added     = 0;
00504 
00505   /* Now change the elem pointer from a dim to a dim_nba */
00506   expr->elem.dim_nba      = (dim_and_nba*)malloc_safe( sizeof( dim_and_nba ) );
00507   expr->elem.dim_nba->dim = dim;
00508   expr->elem.dim_nba->nba = nba;
00509 
00510   /* Set the nba supplemental bit */
00511   expr->suppl.part.nba = 1;
00512 
00513   /* Increment the number of nba structures */
00514   nba_queue_size++;
00515 
00516   PROFILE_END;
00517 
00518 }

void expression_db_merge expression base,
char **  line,
bool  same
 

Reads and merges two expressions and stores result in base expression.

Exceptions:
anonymous Throw vector_db_merge
Parses specified line for expression information and merges contents into the base expression. If the two expressions given are not the same (IDs, op, and/or line position differ) we know that the database files being merged were not created from the same design; therefore, display an error message to the user in this case. If both expressions are the same, perform the merge.
Parameters:
base  Expression to merge data into
line  Pointer to CDD line to parse
same  Specifies if expression to be merged needs to be exactly the same as the existing expression

01739   { PROFILE(EXPRESSION_DB_MERGE);
01740 
01741   int          id;             /* Expression ID field */
01742   int          linenum;        /* Expression line number */
01743   unsigned int column;         /* Column information */
01744   uint32       exec_num;       /* Execution number */
01745   uint32       op;             /* Expression operation */
01746   esuppl       suppl;          /* Supplemental field */
01747   int          right_id;       /* ID of right child */
01748   int          left_id;        /* ID of left child */
01749   int          chars_read;     /* Number of characters read */
01750 
01751   assert( base != NULL );
01752 
01753   if( sscanf( *line, "%d %d %x %x %x %x %d %d%n", &id, &linenum, &column, &exec_num, &op, &(suppl.all), &right_id, &left_id, &chars_read ) == 8 ) {
01754 
01755     *line = *line + chars_read;
01756 
01757     if( (base->op != op) || (base->line != linenum) || (base->col != column) ) {
01758 
01759       print_output( "Attempting to merge databases derived from different designs.  Unable to merge",
01760                     FATAL, __FILE__, __LINE__ );
01761       Throw 0;
01762 
01763     } else {
01764 
01765       /* Merge expression supplemental fields */
01766       base->suppl.all = (base->suppl.all & ESUPPL_MERGE_MASK) | (suppl.all & ESUPPL_MERGE_MASK);
01767 
01768       /* Merge execution number information */
01769       if( base->exec_num < exec_num ) {
01770         base->exec_num = exec_num;
01771       }
01772 
01773       if( ESUPPL_OWNS_VEC( suppl ) ) {
01774 
01775         /* Merge expression vectors */
01776         vector_db_merge( base->value, line, same );
01777 
01778       }
01779 
01780     }
01781 
01782   } else {
01783 
01784     print_output( "Unable to parse expression line in database.  Unable to merge.", FATAL, __FILE__, __LINE__ );
01785     Throw 0;
01786 
01787   }
01788 
01789   PROFILE_END;
01790 
01791 }

void expression_db_read char **  line,
func_unit curr_funit,
bool  eval
 

Reads current line of specified file and parses for expression information.

Exceptions:
anonymous expression_create Throw Throw Throw Throw Throw vector_db_read
Reads in the specified expression information, creates new expression from heap, populates the expression with specified information from file and returns that value in the specified expression pointer. If all is successful, returns TRUE; otherwise, returns FALSE.
Parameters:
line  String containing database line to read information from
curr_funit  Pointer to current functional unit that instantiates this expression
eval  If TRUE, evaluate expression if children are static

01586   { PROFILE(EXPRESSION_DB_READ);
01587 
01588   expression*  expr;        /* Pointer to newly created expression */
01589   int          linenum;     /* Holder of current line for this expression */
01590   unsigned int column;      /* Holder of column alignment information */
01591   uint32       exec_num;    /* Holder of expression's execution number */
01592   uint32       op;          /* Holder of expression operation */
01593   esuppl       suppl;       /* Holder of supplemental value of this expression */
01594   int          right_id;    /* Holder of expression ID to the right */
01595   int          left_id;     /* Holder of expression ID to the left */
01596   expression*  right;       /* Pointer to current expression's right expression */
01597   expression*  left;        /* Pointer to current expression's left expression */
01598   int          chars_read;  /* Number of characters scanned in from line */
01599   vector*      vec;         /* Holders vector value of this expression */
01600   exp_link*    expl;        /* Pointer to found expression in functional unit */
01601 
01602   if( sscanf( *line, "%d %d %x %x %x %x %d %d%n", &curr_expr_id, &linenum, &column, &exec_num, &op, &(suppl.all), &right_id, &left_id, &chars_read ) == 8 ) {
01603 
01604     *line = *line + chars_read;
01605 
01606     /* Find functional unit instance name */
01607     if( curr_funit == NULL ) {
01608 
01609       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Internal error:  expression (%d) in database written before its functional unit", curr_expr_id );
01610       assert( rv < USER_MSG_LENGTH );
01611       print_output( user_msg, FATAL, __FILE__, __LINE__ );
01612       Throw 0;
01613 
01614     } else {
01615 
01616       /* Find right expression */
01617       if( right_id == 0 ) {
01618         right = NULL;
01619       } else if( (expl = exp_link_find( right_id, curr_funit->exp_head )) == NULL ) {
01620         unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Internal error:  root expression (%d) found before leaf expression (%d) in database file", curr_expr_id, right_id );
01621         assert( rv < USER_MSG_LENGTH );
01622         print_output( user_msg, FATAL, __FILE__, __LINE__ );
01623         Throw 0;
01624       } else {
01625         right = expl->exp;
01626       }
01627 
01628       /* Find left expression */
01629       if( left_id == 0 ) {
01630         left = NULL;
01631       } else if( (expl = exp_link_find( left_id, curr_funit->exp_head )) == NULL ) {
01632         unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Internal error:  root expression (%d) found before leaf expression (%d) in database file", curr_expr_id, left_id );
01633         assert( rv < USER_MSG_LENGTH );
01634         print_output( user_msg, FATAL, __FILE__, __LINE__ );
01635         Throw 0;
01636       } else {
01637         left = expl->exp;
01638       }
01639 
01640       /* Create new expression */
01641       expr = expression_create( right, left, op, ESUPPL_IS_LHS( suppl ), curr_expr_id, linenum,
01642                                 ((column >> 16) & 0xffff), (column & 0xffff), ESUPPL_OWNS_VEC( suppl ) );
01643 
01644       expr->suppl.all = suppl.all;
01645       expr->exec_num  = exec_num;
01646 
01647       if( op == EXP_OP_DELAY ) {
01648         expr->suppl.part.type = ETYPE_DELAY;
01649         expr->elem.scale = &(curr_funit->timescale);
01650       }
01651 
01652       if( ESUPPL_OWNS_VEC( suppl ) ) {
01653 
01654         Try {
01655 
01656           /* Read in vector information */
01657           vector_db_read( &vec, line );
01658 
01659         } Catch_anonymous {
01660           expression_dealloc( expr, TRUE );
01661           Throw 0;
01662         }
01663 
01664         /* Copy expression value */
01665         vector_dealloc( expr->value );
01666         expr->value = vec;
01667 
01668       }
01669 
01670       /* Create temporary vectors if necessary */
01671       expression_create_tmp_vecs( expr, expr->value->width );
01672 
01673       /* Check to see if we are bound to a signal or functional unit */
01674       if( ((*line)[0] != '\n') && ((*line)[0] != '\0') ) {
01675         (*line)++;   /* Remove space */
01676         switch( op ) {
01677           case EXP_OP_FUNC_CALL :  bind_add( FUNIT_FUNCTION,    *line, expr, curr_funit );  break;
01678           case EXP_OP_TASK_CALL :  bind_add( FUNIT_TASK,        *line, expr, curr_funit );  break;
01679           case EXP_OP_FORK      :
01680           case EXP_OP_NB_CALL   :  bind_add( FUNIT_NAMED_BLOCK, *line, expr, curr_funit );  break;
01681           case EXP_OP_DISABLE   :  bind_add( 1,                 *line, expr, curr_funit );  break;
01682           default               :  bind_add( 0,                 *line, expr, curr_funit );  break;
01683         }
01684       }
01685 
01686       /* If we are an assignment operator, set our vector value to that of the right child */
01687       if( (op == EXP_OP_ASSIGN)     ||
01688           (op == EXP_OP_DASSIGN)    ||
01689           (op == EXP_OP_BASSIGN)    ||
01690           (op == EXP_OP_RASSIGN)    ||
01691           (op == EXP_OP_NASSIGN)    ||
01692           (op == EXP_OP_DLY_ASSIGN) ||
01693           (op == EXP_OP_IF)         ||
01694           (op == EXP_OP_WHILE)      ||
01695           (op == EXP_OP_DIM) ) {
01696 
01697         vector_dealloc( expr->value );
01698         expr->value = right->value;
01699 
01700       }
01701 
01702       exp_link_add( expr, &(curr_funit->exp_head), &(curr_funit->exp_tail) );
01703 
01704       /*
01705        If this expression is a constant expression, force the simulator to evaluate
01706        this expression and all parent expressions of it.
01707       */
01708       if( eval && EXPR_IS_STATIC( expr ) && (ESUPPL_IS_LHS( suppl ) == 0) ) {
01709         exp_link_add( expr, &static_expr_head, &static_expr_tail );
01710       }
01711       
01712     }
01713 
01714   } else {
01715 
01716     print_output( "Unable to read expression value", FATAL, __FILE__, __LINE__ );
01717     Throw 0;
01718 
01719   }
01720 
01721   PROFILE_END;
01722 
01723 }

void expression_db_write expression expr,
FILE *  file,
bool  parse_mode,
bool  ids_issued
 

Writes this expression to the specified database file.

This function recursively displays the expression information for the specified expression tree to the coverage database specified by file.

Parameters:
expr  Pointer to expression to write to database file
file  Pointer to database file to write to
parse_mode  Set to TRUE when we are writing after just parsing the design (causes ulid value to be output instead of id)
ids_issued  Set to TRUE if IDs were issued prior to calling this function

01512   { PROFILE(EXPRESSION_DB_WRITE);
01513 
01514   assert( expr != NULL );
01515 
01516   fprintf( file, "%d %d %d %x %x %x %x %d %d",
01517     DB_TYPE_EXPRESSION,
01518     expression_get_id( expr, ids_issued ),
01519     expr->line,
01520     expr->col,
01521     ((((expr->op == EXP_OP_DASSIGN) || (expr->op == EXP_OP_ASSIGN)) && (expr->exec_num == 0)) ? (uint32)1 : expr->exec_num),
01522     expr->op,
01523     (expr->suppl.all & ESUPPL_MERGE_MASK),
01524     ((expr->op == EXP_OP_STATIC) ? 0 : expression_get_id( expr->right, ids_issued )),
01525     ((expr->op == EXP_OP_STATIC) ? 0 : expression_get_id( expr->left,  ids_issued ))
01526   );
01527 
01528   if( ESUPPL_OWNS_VEC( expr->suppl ) ) {
01529     fprintf( file, " " );
01530     if( parse_mode && EXPR_OWNS_VEC( expr->op ) && (expr->value->suppl.part.owns_data == 0) ) {
01531       expr->value->suppl.part.owns_data = 1;
01532     }
01533     vector_db_write( expr->value, file, (expr->op == EXP_OP_STATIC), FALSE );
01534   }
01535 
01536   if( expr->name != NULL ) {
01537     fprintf( file, " %s", expr->name );
01538   } else if( expr->sig != NULL ) {
01539     fprintf( file, " %s", expr->sig->name );  /* This will be valid for parameters */
01540   }
01541 
01542   fprintf( file, "\n" );
01543 
01544   PROFILE_END;
01545 
01546 }

void expression_db_write_tree expression root,
FILE *  ofile
 

Writes the entire expression tree to the specified data file.

Recursively iterates through the specified expression tree, outputting the expressions to the specified file.

Parameters:
root  Pointer to the root expression to display
ofile  Output file to write expression tree to

01555   { PROFILE(EXPRESSION_DB_WRITE_TREE);
01556 
01557   if( root != NULL ) {
01558 
01559     /* Print children first */
01560     if( EXPR_LEFT_DEALLOCABLE( root ) ) {
01561       expression_db_write_tree( root->left, ofile );
01562     }
01563     expression_db_write_tree( root->right, ofile );
01564 
01565     /* Now write ourselves */
01566     expression_db_write( root, ofile, TRUE, TRUE );
01567 
01568   }
01569 
01570   PROFILE_END;
01571 
01572 }

void expression_dealloc expression expr,
bool  exp_only
 

Deallocates memory used for expression.

Deallocates all heap memory allocated with the malloc routine.

Parameters:
expr  Pointer to root expression to deallocate
exp_only  Removes only the specified expression and not its children

06167   { PROFILE(EXPRESSION_DEALLOC);
06168 
06169   int        op;        /* Temporary operation holder */
06170   exp_link*  tmp_expl;  /* Temporary pointer to expression list */
06171   statement* tmp_stmt;  /* Temporary pointer to statement */
06172 
06173   if( expr != NULL ) {
06174 
06175     op = expr->op;
06176 
06177     if( ESUPPL_OWNS_VEC( expr->suppl ) ) {
06178 
06179       /* Free up memory from vector value storage */
06180       vector_dealloc( expr->value );
06181       expr->value = NULL;
06182 
06183       /* If this is a named block call or fork call, remove the statement that this expression points to */
06184       if( (expr->op == EXP_OP_NB_CALL) || (expr->op == EXP_OP_FORK) ) {
06185 
06186         if( !exp_only && (expr->elem.funit != NULL) ) {
06187 #ifdef DEBUG_MODE
06188           if( debug_mode ) {
06189             unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Removing statement block starting at line %d because it is a NB_CALL and its calling expression is being removed",
06190                                         expr->elem.funit->first_stmt->exp->line );
06191             assert( rv < USER_MSG_LENGTH );
06192             print_output( user_msg, DEBUG, __FILE__, __LINE__ );
06193           }
06194 #endif
06195           stmt_blk_add_to_remove_list( expr->elem.funit->first_stmt );
06196         } else {
06197           bind_remove( expr->id, FALSE );
06198         }
06199 
06200       /* If this is a task call, remove the bind */
06201       } else if( expr->op == EXP_OP_TASK_CALL ) {
06202          
06203         bind_remove( expr->id, FALSE );
06204 
06205       } else if( expr->op == EXP_OP_FUNC_CALL ) {
06206 
06207         /* Remove this expression from the attached signal's expression list (if the signal has not been deallocated yet) */
06208         if( expr->sig != NULL ) {
06209           exp_link_remove( expr, &(expr->sig->exp_head), &(expr->sig->exp_tail), FALSE );
06210         }
06211 
06212         bind_remove( expr->id, FALSE );
06213 
06214       /* Otherwise, we assume (for now) that the expression is a signal */
06215       } else {
06216 
06217         if( expr->sig == NULL ) {
06218 
06219           /* Remove this expression from the binding list */
06220           bind_remove( expr->id, expression_is_assigned( expr ) );
06221 
06222         } else {
06223 
06224           /* Remove this expression from the attached signal's expression list */
06225           exp_link_remove( expr, &(expr->sig->exp_head), &(expr->sig->exp_tail), FALSE );
06226 
06227           /* Clear the assigned bit of the attached signal */
06228           if( expression_is_assigned( expr ) ) {
06229   
06230             expr->sig->suppl.part.assigned = 0;
06231 
06232             /* If this signal must be assigned, remove all statement blocks that reference this signal */
06233             if( (expr->sig->suppl.part.mba == 1) && !exp_only ) {
06234               tmp_expl = expr->sig->exp_head;
06235               while( tmp_expl != NULL ) {
06236                 if( (tmp_stmt = expression_get_root_statement( tmp_expl->exp )) != NULL ) {
06237 #ifdef DEBUG_MODE
06238                   if( debug_mode ) {
06239                     print_output( "Removing statement block because a statement block is being removed that assigns an MBA", DEBUG, __FILE__, __LINE__ );
06240                   }
06241 #endif
06242                   stmt_blk_add_to_remove_list( tmp_stmt );
06243                 }
06244                 tmp_expl = tmp_expl->next;
06245               }
06246             }
06247 
06248           }
06249         
06250         }
06251 
06252       }
06253 
06254     } else {
06255 
06256       /* Remove our expression from its signal, if we have one */
06257       if( expr->sig != NULL ) {
06258         exp_link_remove( expr, &(expr->sig->exp_head), &(expr->sig->exp_tail), FALSE );
06259       }
06260 
06261     }
06262 
06263     /* Deallocate children */
06264     if( !exp_only ) {
06265 
06266       if( EXPR_RIGHT_DEALLOCABLE( expr ) ) {
06267         expression_dealloc( expr->right, FALSE );
06268         expr->right = NULL;
06269       }
06270 
06271       if( EXPR_LEFT_DEALLOCABLE( expr ) ) {
06272         expression_dealloc( expr->left, FALSE );
06273         expr->left = NULL;
06274       }
06275 
06276     }
06277 
06278     /* If we have temporary vectors to deallocate, do so now */
06279     if( (expr->elem.tvecs != NULL) && (EXPR_TMP_VECS( expr->op ) > 0) ) {
06280       unsigned int i;
06281       for( i=0; i<EXPR_TMP_VECS( expr->op ); i++ ) {
06282         vector_dealloc_value( &(expr->elem.tvecs->vec[i]) );
06283       }
06284       free_safe( expr->elem.tvecs, sizeof( vecblk ) );
06285     }
06286 
06287     /* If we have expression dimensional information, deallocate it now */
06288     if( (expr->elem.dim != NULL) && EXPR_OP_HAS_DIM( expr->op ) ) {
06289       if( expr->suppl.part.nba == 1 ) {
06290         free_safe( expr->elem.dim_nba->dim, sizeof( exp_dim ) );
06291         free_safe( expr->elem.dim_nba->nba, sizeof( nonblock_assign ) );
06292         free_safe( expr->elem.dim_nba, sizeof( dim_and_nba ) );
06293       } else {
06294         free_safe( expr->elem.dim, sizeof( exp_dim ) );
06295       }
06296     }
06297 
06298     /* Free up memory for the parent pointer */
06299     free_safe( expr->parent, sizeof( expr_stmt ) );
06300 
06301     /* If name contains data, free it */
06302     free_safe( expr->name, (strlen( expr->name ) + 1) );
06303 
06304     /* Remove this expression memory */
06305     free_safe( expr, sizeof( expression ) );
06306 
06307   }
06308 
06309   PROFILE_END;
06310 
06311 }

void expression_display expression expr  ) 
 

Displays the specified expression information.

Displays contents of the specified expression to standard output. This function is called by the funit_display function.

Parameters:
expr  Pointer to expression to display

01862   {
01863 
01864   int right_id;  /* Value of right expression ID */
01865   int left_id;   /* Value of left expression ID */
01866 
01867   assert( expr != NULL );
01868 
01869   if( expr->left == NULL ) {
01870     left_id = 0;
01871   } else {
01872     left_id = expr->left->id;
01873   }
01874 
01875   if( expr->right == NULL ) {
01876     right_id = 0;
01877   } else {
01878     right_id = expr->right->id;
01879   }
01880 
01881   printf( "  Expression (%p) =>  id: %d, op: %s, line: %d, col: %x, suppl: %x, exec_num: %u, left: %d, right: %d, ", 
01882           expr,
01883           expr->id,
01884           expression_string_op( expr->op ),
01885           expr->line,
01886           expr->col,
01887           expr->suppl.all,
01888           expr->exec_num,
01889           left_id, 
01890           right_id );
01891 
01892   if( expr->value->value.ul == NULL ) {
01893     printf( "NO DATA VECTOR" );
01894   } else {
01895     switch( expr->value->suppl.part.data_type ) {
01896       case VDATA_UL  :  vector_display_value_ulong( expr->value->value.ul, expr->value->width );  break;
01897       case VDATA_R64 :
01898         if( expr->value->value.r64->str != NULL ) {
01899           printf( "%s", expr->value->value.r64->str );
01900         } else {
01901           printf( "%.16lf", expr->value->value.r64->val );
01902         }
01903         break;
01904       case VDATA_R32 :
01905         if( expr->value->value.r32->str != NULL ) {
01906           printf( "%s", expr->value->value.r32->str );
01907         } else {
01908           printf( "%.16f", expr->value->value.r32->val );
01909         }
01910         break;
01911       default :  assert( 0 );  break;
01912     }
01913   }
01914   printf( "\n" );
01915 
01916 }

bool expression_find_expr expression root,
expression expr
 

Returns TRUE if the specified expression exists within the given root expression tree.

Returns:
Returns TRUE if the given expression exists within the given expression tree; otherwise, returns FALSE
Parameters:
root  Pointer to root of expression tree to search
expr  Pointer to expression to search for

01416   { PROFILE(EXPRESSION_FIND_EXPR);
01417 
01418   bool retval = (root != NULL) && ((root == expr) || expression_find_expr( root->left, expr ) || expression_find_expr( root->right, expr ));
01419 
01420   PROFILE_END;
01421 
01422   return( retval );
01423 
01424 }

void expression_find_rhs_sigs expression expr,
str_link **  head,
str_link **  tail
 

Finds all RHS signals in given expression tree.

Recursively parses specified expression list in search of RHS signals. When a signal name is found, it is added to the signal name list specified by head and tail.

Parameters:
expr  Pointer to expression tree to parse
head  Pointer to head of signal name list to populate
tail  Pointer to tail of signal name list to populate

01304   { PROFILE(EXPRESSION_FIND_RHS_SIGS);
01305 
01306   char* sig_name;  /* Name of signal found */
01307 
01308   /* Only continue if our expression is valid and it is an RHS */
01309   if( (expr != NULL) && (ESUPPL_IS_LHS( expr->suppl ) == 0) ) {
01310 
01311     if( (expr->op == EXP_OP_SIG)      ||
01312         (expr->op == EXP_OP_TRIGGER)  ||
01313         (expr->op == EXP_OP_SBIT_SEL) ||
01314         (expr->op == EXP_OP_MBIT_SEL) ||
01315         (expr->op == EXP_OP_MBIT_POS) ||
01316         (expr->op == EXP_OP_MBIT_NEG) ) {
01317  
01318       /* Get the signal name from the binder */
01319       sig_name = bind_find_sig_name( expr );
01320        
01321       assert( sig_name != NULL );
01322     
01323       /* If the signal isn't already in the list, add it */
01324       if( str_link_find( sig_name, *head ) == NULL ) {
01325         (void)str_link_add( sig_name, head, tail );
01326       } else {
01327         free_safe( sig_name, (strlen( sig_name ) + 1) );
01328       }
01329 
01330     }
01331 
01332     /* If this expression operation is neither a SIG or TRIGGER, keep searching tree */
01333     if( (expr->op != EXP_OP_SIG) && (expr->op != EXP_OP_TRIGGER) ) {
01334 
01335       expression_find_rhs_sigs( expr->right, head, tail );
01336       expression_find_rhs_sigs( expr->left,  head, tail );
01337 
01338     }
01339 
01340   }
01341 
01342   PROFILE_END;
01343 
01344 }

expression* expression_find_uline_id expression expr,
int  ulid
 

Finds the expression in this expression tree with the specified underline id.

Returns:
Returns a pointer to the found expression; otherwise, returns NULL if the expression could not be found.
Recursively searches the given expression tree for the specified underline ID. If the expression is found, a pointer to it is returned; otherwise, returns NULL.
Parameters:
expr  Pointer to root expression to search under
ulid  Underline ID to search for

01387   { PROFILE(EXPRESSION_FIND_ULINE_ID);
01388 
01389   expression* found_exp = NULL;  /* Pointer to found expression */
01390 
01391   if( expr != NULL ) {
01392 
01393     if( expr->ulid == ulid ) {
01394       found_exp = expr;
01395     } else {
01396       if( (found_exp = expression_find_uline_id( expr->left, ulid )) == NULL ) {
01397         found_exp = expression_find_uline_id( expr->right, ulid );
01398       }
01399     }
01400 
01401   }
01402 
01403   PROFILE_END;
01404 
01405   return( found_exp );
01406 
01407 }

unsigned int expression_get_curr_dimension expression expr  ) 
 

Returns the current dimension of the given expression.

Returns:
Returns the dimension index for the given expression
Recursively iterates up expression tree, counting the number of dimensions deep that the given expression is.
Parameters:
expr  Pointer to expression to get dimension for

01267   { PROFILE(EXPRESSION_GET_CURR_DIMENSION);
01268   
01269   unsigned int dim;  /* Return value for this function */
01270 
01271   assert( expr != NULL );
01272 
01273   if( expr->op == EXP_OP_DIM ) {
01274 
01275     dim = expression_get_curr_dimension( expr->left ) + 1;
01276 
01277   } else {
01278 
01279     if( (ESUPPL_IS_ROOT( expr->suppl ) == 0) &&
01280         (expr->parent->expr->op == EXP_OP_DIM) && 
01281         (expr->parent->expr->right == expr) ) {
01282       dim = expression_get_curr_dimension( expr->parent->expr );
01283     } else {
01284       dim = 0;
01285     }
01286 
01287   }
01288 
01289   PROFILE_END;
01290 
01291   return( dim );
01292 
01293 }

expression* expression_get_first_line_expr expression expr  ) 
 

Returns first line in this expression tree.

Returns:
Returns the line number of the first line in this expression.
Parameters:
expr  Pointer to root expression to extract first line from

01216   { PROFILE(EXPRESSION_GET_FIRST_LINE_EXPR);
01217 
01218   expression* first = NULL;
01219 
01220   if( expr != NULL ) {
01221 
01222     first = expression_get_first_line_expr( expr->left );
01223     if( (first == NULL) || (first->line > expr->line) ) {
01224       first = expr;
01225     }
01226 
01227   }
01228 
01229   PROFILE_END;
01230 
01231   return( first );
01232 
01233 }

int expression_get_id expression expr,
bool  parse_mode
 

Returns expression ID of this expression.

Returns:
Returns expression ID for this expression.
If specified expression is non-NULL, return expression ID of this expression; otherwise, return a value of 0 to indicate that this is a leaf node.
Parameters:
expr  Pointer to expression to get ID from
parse_mode  Specifies if ulid (TRUE) or id (FALSE) should be used

01195   { PROFILE(EXPRESSION_GET_ID);
01196 
01197   int id;
01198 
01199   if( expr == NULL ) {
01200     id = 0;
01201   } else {
01202     id = parse_mode ? expr->ulid : expr->id;
01203   }
01204 
01205   PROFILE_END;
01206 
01207   return( id );
01208 
01209 }

expression* expression_get_last_line_expr expression expr  ) 
 

Returns last line in this expression tree.

Returns:
Returns the line number of the last line in this expression.
Parameters:
expr  Pointer to root expression to extract last line from

01240   { PROFILE(EXPRESSION_GET_LAST_LINE_EXPR);
01241 
01242   expression* last = NULL;
01243 
01244   if( expr != NULL ) {
01245 
01246     last = expression_get_last_line_expr( expr->right );
01247     if( (last == NULL) || (last->line < expr->line) ) {
01248       last = expr;
01249     }
01250       
01251   }
01252 
01253   PROFILE_END;
01254 
01255   return( last );
01256 
01257 }

statement* expression_get_root_statement expression exp  ) 
 

Finds the root statement for the given expression.

Returns:
Returns a pointer to the root statement of the specified expression if one exists; otherwise, returns NULL.
Recursively traverses up expression tree that contains exp until the root expression is found (if one exists). If the root expression is found, return the pointer to the statement pointing to this root expression. If the root expression was not found, return NULL.
Parameters:
exp  Pointer to expression to get root statement for

01455   { PROFILE(EXPRESSION_GET_ROOT_STATEMENT);
01456 
01457   statement* stmt;  /* Pointer to root statement */
01458 
01459   if( exp == NULL ) {
01460     stmt = NULL;
01461   } else if( ESUPPL_IS_ROOT( exp->suppl ) == 1 ) {
01462     stmt = exp->parent->stmt;
01463   } else {
01464     stmt = expression_get_root_statement( exp->parent->expr );
01465   }
01466 
01467   PROFILE_END;
01468 
01469   return( stmt );
01470 
01471 }

bool expression_is_bit_select expression expr  ) 
 

Returns TRUE if specified expression is a part of an bit select expression tree.

Returns:
Returns TRUE if the specifies expression belongs in a single or mult-bit select expression
Parameters:
expr  Pointer to expression to check

05771   { PROFILE(EXPRESSION_IS_BIT_SELECT);
05772 
05773   bool retval = FALSE;  /* Return value for this function */
05774 
05775   if( (expr != NULL) && (ESUPPL_IS_ROOT( expr->suppl ) == 0) ) {
05776 
05777     if( (expr->parent->expr->op == EXP_OP_SBIT_SEL) ||
05778         (expr->parent->expr->op == EXP_OP_MBIT_SEL) ||
05779         (expr->parent->expr->op == EXP_OP_MBIT_POS) ||
05780         (expr->parent->expr->op == EXP_OP_MBIT_NEG) ) {
05781       retval = TRUE;
05782     } else {
05783       retval = expression_is_bit_select( expr->parent->expr );
05784     }
05785 
05786   }
05787 
05788   PROFILE_END;
05789 
05790   return( retval );
05791 
05792 }

bool expression_is_in_rassign expression expr  ) 
 

Returns TRUE if specified expression is in an RASSIGN expression tree.

Returns:
Returns TRUE if the specified expression is in an RASSIGN expression tree; otherwise, returns FALSE.
Parameters:
expr  Pointer to expression to examine

05821   { PROFILE(EXPRESSION_IS_IN_RASSIGN);
05822 
05823   bool retval = FALSE;  /* Return value for this function */
05824 
05825   if( expr != NULL ) {
05826 
05827     if( expr->op == EXP_OP_RASSIGN ) {
05828       retval = TRUE;
05829     } else if( ESUPPL_IS_ROOT( expr->suppl ) == 0 ) {
05830       retval = expression_is_in_rassign( expr->parent->expr );
05831     }
05832 
05833   }
05834 
05835   PROFILE_END;
05836 
05837   return( retval );
05838 
05839 }

bool expression_is_last_select expression expr  ) 
 

Returns TRUE if specified expression is the last select of a signal.

Returns:
Returns TRUE if the specified expression is the last (most right-hand) part/bit select of a signal; otherwise, returns FALSE.
Parameters:
expr  Pointer to expression to check for last select

05800   { PROFILE(EXPRESSION_IS_LAST_SELECT);
05801 
05802   bool retval = (ESUPPL_IS_ROOT( expr->suppl ) == 1) ||
05803                 ( ((expr->parent->expr->op == EXP_OP_DIM) &&
05804                    (expr->parent->expr->right == expr) &&
05805                    (ESUPPL_IS_ROOT( expr->parent->expr->suppl ) == 0) &&
05806                    (expr->parent->expr->parent->expr->op != EXP_OP_DIM)) ||
05807                   (expr->parent->expr->op != EXP_OP_DIM) );
05808 
05809   PROFILE_END;
05810 
05811   return( retval );
05812 
05813 }

expression* expression_is_nba_lhs expression exp  ) 
 

Returns a pointer to the non-blocking assignment expression if the given expression is an assignable expression on the LHS of a non-blocking assignment.

Returns:
Returns a pointer to the non-blocking assignment if this expression is a child of the LHS that will be assigned via a non-blocking assignment; otherwise, returns a value of NULL.
Parameters:
exp  Pointer to child expression to check

00526   { PROFILE(EXPRESSION_IS_NBA_LHS);
00527 
00528   while( (exp->op != EXP_OP_NASSIGN)                &&
00529          (ESUPPL_IS_ROOT( exp->suppl ) == 0)        &&
00530          (exp->parent->expr->op != EXP_OP_SBIT_SEL) &&
00531          (exp->parent->expr->op != EXP_OP_MBIT_SEL) &&
00532          (exp->parent->expr->op != EXP_OP_MBIT_POS) &&
00533          (exp->parent->expr->op != EXP_OP_MBIT_NEG) ) {
00534     exp = exp->parent->expr;
00535   }
00536 
00537   PROFILE_END;
00538 
00539   return( (exp->op == EXP_OP_NASSIGN) ? exp : NULL );
00540 
00541 }

bool expression_is_static_only expression expr  ) 
 

Returns TRUE if specified expression is found to contain all static leaf expressions.

Parameters:
expr  Pointer to expression to evaluate

05716   {
05717 
05718   return( expression_is_static_only_helper( expr, NULL ) ); 
05719 
05720 }

void expression_merge expression base,
expression other
 

Merges two expressions into the base expression.

Performs an expression merge of two expressions, storing the result into the base expression. This function is used by the GUI for calculating module coverage.

Parameters:
base  Base expression that will contain merged results
other  Other expression that will merge its results with the base results

01800   { PROFILE(EXPRESSION_MERGE);
01801 
01802   assert( base != NULL );
01803   assert( base->op   == other->op );
01804   assert( base->line == other->line );
01805   assert( base->col  == other->col );
01806 
01807   /* Merge expression supplemental fields */
01808   base->suppl.all = (base->suppl.all & ESUPPL_MERGE_MASK) | (other->suppl.all & ESUPPL_MERGE_MASK);
01809 
01810   /* Merge execution number information */
01811   if( base->exec_num < other->exec_num ) {
01812     base->exec_num = other->exec_num;
01813   }
01814 
01815   if( ESUPPL_OWNS_VEC( base->suppl ) ) {
01816     vector_merge( base->value, other->value );
01817   }
01818 
01819   PROFILE_END;
01820 
01821 }

bool expression_operate expression expr,
thread thr,
const sim_time time
 

Performs operation specified by parameter expression.

Returns:
Returns TRUE if the assigned expression value was different than the previously stored value; otherwise, returns FALSE.
Exceptions:
anonymous func
Performs expression operation. This function must only be run after its left and right expressions have been calculated during this clock period. Sets the value of the operation in its own vector value and updates the suppl uint8 as necessary.
Parameters:
expr  Pointer to expression to set value to
thr  Pointer to current thread being simulated
time  Pointer to current simulation time

05565   { PROFILE(EXPRESSION_OPERATE);
05566 
05567   bool retval = TRUE;  /* Return value for this function */
05568 
05569   if( expr != NULL ) {
05570 
05571 #ifdef DEBUG_MODE
05572     if( debug_mode ) {
05573       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "      In expression_operate, id: %d, op: %s, line: %d, addr: %p",
05574                                   expr->id, expression_string_op( expr->op ), expr->line, expr );
05575       assert( rv < USER_MSG_LENGTH );
05576       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
05577     }
05578 #endif
05579 
05580     assert( expr->value != NULL );
05581 
05582     /* Call expression operation */
05583     retval = exp_op_info[expr->op].func( expr, thr, time );
05584 
05585     /* If this expression is attached to an FSM, perform the FSM calculation now */
05586     if( expr->table != NULL ) {
05587       fsm_table_set( expr, time );
05588     }
05589 
05590     /* Specify that we have executed this expression */
05591     (expr->exec_num)++;
05592 
05593   }
05594 
05595   PROFILE_END;
05596 
05597   return( retval );
05598 
05599 }

void expression_operate_recursively expression expr,
func_unit funit,
bool  sizing
 

Performs recursive expression operation (parse mode only).

Exceptions:
anonymous expression_resize expression_operate_recursively expression_operate_recursively
Recursively performs the proper operations to cause the top-level expression to be set to a value. This function is called during the parse stage to derive pre-CDD widths of multi-bit expressions. Each MSB/LSB is an expression tree that needs to be evaluated to set the width properly on the MBIT_SEL expression.
Parameters:
expr  Pointer to top of expression tree to perform recursive operations
funit  Pointer to functional unit containing this expression
sizing  Set to TRUE if we are evaluating for purposes of sizing

05613   { PROFILE(EXPRESSION_OPERATE_RECURSIVELY);
05614     
05615   if( expr != NULL ) {
05616     
05617     /* Create dummy time */
05618     sim_time time = {0,0,0,FALSE};
05619 
05620     /* Evaluate children */
05621     expression_operate_recursively( expr->left,  funit, sizing );
05622     expression_operate_recursively( expr->right, funit, sizing );
05623     
05624     if( sizing ) {
05625 
05626       /*
05627        Non-static expression found where static expression required.  Simulator
05628        should catch this error before us, so no user error (too much work to find
05629        expression in functional unit expression list for now.
05630       */
05631       assert( (expr->op != EXP_OP_SBIT_SEL) &&
05632               (expr->op != EXP_OP_MBIT_SEL) &&
05633               (expr->op != EXP_OP_MBIT_POS) &&
05634               (expr->op != EXP_OP_MBIT_NEG) );
05635 
05636       /* Resize current expression only */
05637       expression_resize( expr, funit, FALSE, TRUE );
05638     
05639     }
05640     
05641     /* Perform operation */
05642     (void)expression_operate( expr, NULL, &time );
05643 
05644     if( sizing ) {
05645 
05646       /* Clear out the execution number value since we aren't really simulating this */
05647       expr->exec_num = 0;
05648 
05649     }
05650     
05651   }
05652   
05653   PROFILE_END;
05654 
05655 }

void expression_resize expression expr,
func_unit funit,
bool  recursive,
bool  alloc
 

Recursively resizes specified expression tree leaf node.

Exceptions:
anonymous expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value expression_create_value funit_size_elements expression_resize expression_resize expression_operate_recursively expression_set_value
Resizes the given expression depending on the expression operation and its children's sizes. If recursive is TRUE, performs the resize in a depth-first fashion, resizing the children before resizing the current expression. If recursive is FALSE, only the given expression is evaluated and resized.
Parameters:
expr  Pointer to expression to potentially resize
funit  Pointer to functional unit containing expression
recursive  Specifies if we should perform a recursive depth-first resize
alloc  If set to TRUE, allocates vector data for all expressions

00979   { PROFILE(EXPRESSION_RESIZE);
00980 
00981   unsigned int largest_width;  /* Holds larger width of left and right children */
00982   uint8        old_vec_suppl;  /* Holds original vector supplemental field as this will be erased */
00983   funit_inst*  tmp_inst;       /* Pointer to temporary instance */
00984   int          ignore = 0;     /* Specifies the number of instances to ignore */
00985 
00986   if( expr != NULL ) {
00987 
00988     uint8 new_owns_data;
00989     uint8 new_data_type;
00990 
00991     if( recursive ) {
00992       expression_resize( expr->left, funit, recursive, alloc );
00993       expression_resize( expr->right, funit, recursive, alloc );
00994     }
00995 
00996     /* Get vector supplemental field */
00997     old_vec_suppl = expr->value->suppl.all;
00998 
00999     switch( expr->op ) {
01000 
01001       /* Only resize these values if we are recursively resizing */
01002       case EXP_OP_PARAM          :
01003       case EXP_OP_PARAM_SBIT     :
01004       case EXP_OP_PARAM_MBIT     :
01005       case EXP_OP_PARAM_MBIT_POS :
01006       case EXP_OP_PARAM_MBIT_NEG :
01007       case EXP_OP_SIG            :
01008       case EXP_OP_SBIT_SEL       :
01009       case EXP_OP_MBIT_SEL       :
01010       case EXP_OP_MBIT_POS       :
01011       case EXP_OP_MBIT_NEG       :
01012         if( recursive && (expr->sig != NULL) ) {
01013           expression_set_value( expr, expr->sig, funit );
01014           assert( expr->value->value.ul != NULL );
01015         }
01016         break;
01017 
01018       /* These operations will already be sized so nothing to do here */
01019       case EXP_OP_STATIC         :
01020       case EXP_OP_TRIGGER        :
01021       case EXP_OP_ASSIGN         :
01022       case EXP_OP_DASSIGN        :
01023       case EXP_OP_BASSIGN        :
01024       case EXP_OP_NASSIGN        :
01025       case EXP_OP_PASSIGN        :
01026       case EXP_OP_RASSIGN        :
01027       case EXP_OP_DLY_ASSIGN     :
01028       case EXP_OP_IF             :
01029       case EXP_OP_WHILE          :
01030       case EXP_OP_LAST           :
01031       case EXP_OP_DIM            :
01032       case EXP_OP_STIME          :
01033       case EXP_OP_SRANDOM        :
01034       case EXP_OP_SURANDOM       :
01035       case EXP_OP_SURAND_RANGE   :
01036         break;
01037 
01038       /* These operations should always be set to a width 1 */
01039       case EXP_OP_LT        :
01040       case EXP_OP_GT        :
01041       case EXP_OP_EQ        :
01042       case EXP_OP_CEQ       :
01043       case EXP_OP_LE        :
01044       case EXP_OP_GE        :
01045       case EXP_OP_NE        :
01046       case EXP_OP_CNE       :
01047       case EXP_OP_LOR       :
01048       case EXP_OP_LAND      :
01049       case EXP_OP_UAND      :
01050       case EXP_OP_UNOT      :
01051       case EXP_OP_UOR       :
01052       case EXP_OP_UXOR      :
01053       case EXP_OP_UNAND     :
01054       case EXP_OP_UNOR      :
01055       case EXP_OP_UNXOR     :
01056       case EXP_OP_EOR       :
01057       case EXP_OP_CASE      :
01058       case EXP_OP_CASEX     :
01059       case EXP_OP_CASEZ     :
01060       case EXP_OP_DEFAULT   :
01061       case EXP_OP_REPEAT    :
01062       case EXP_OP_RPT_DLY   :
01063       case EXP_OP_WAIT      :
01064       case EXP_OP_SFINISH   :
01065       case EXP_OP_SSTOP     :
01066       case EXP_OP_NEDGE     :
01067       case EXP_OP_PEDGE     :
01068       case EXP_OP_AEDGE     :
01069       case EXP_OP_PLIST     :
01070       case EXP_OP_SSRANDOM  :
01071       case EXP_OP_STESTARGS :
01072       case EXP_OP_SVALARGS  : 
01073         if( (expr->value->width != 1) || (expr->value->value.ul == NULL) ) {
01074           assert( expr->value->value.ul == NULL );
01075           expression_create_value( expr, 1, alloc );
01076         }
01077         break;
01078 
01079       /*
01080        In the case of an EXPAND, we need to set the width to be the product of the value of
01081        the left child and the bit-width of the right child.
01082       */
01083       case EXP_OP_EXPAND :
01084         expression_operate_recursively( expr->left, funit, TRUE );
01085         if( vector_is_unknown( expr->left->value ) ) {
01086           unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unknown value used for concatenation multiplier, file: %s, line: %d", funit->filename, expr->line );
01087           assert( rv < USER_MSG_LENGTH );
01088           print_output( user_msg, FATAL, __FILE__, __LINE__ );
01089           Throw 0;
01090         }
01091         if( (expr->value->width != (vector_to_int( expr->left->value ) * expr->right->value->width)) ||
01092             (expr->value->value.ul == NULL) ) {
01093           assert( expr->value->value.ul == NULL );
01094           expression_create_value( expr, (vector_to_int( expr->left->value ) * expr->right->value->width), alloc );
01095         }
01096         break;
01097 
01098       /* 
01099        In the case of a MULTIPLY or LIST (for concatenation) operation, its expression width must be the sum of its
01100        children's width.  Remove the current vector and replace it with the appropriately
01101        sized vector.
01102       */
01103       case EXP_OP_LIST :
01104         if( (expr->value->width != (expr->left->value->width + expr->right->value->width)) ||
01105             (expr->value->value.ul == NULL) ) {
01106           assert( expr->value->value.ul == NULL );
01107           expression_create_value( expr, (expr->left->value->width + expr->right->value->width), alloc );
01108         }
01109         break;
01110 
01111       /*
01112        A FUNC_CALL expression width is set to the same width as that of the function's return value.
01113       */
01114       case EXP_OP_FUNC_CALL :
01115         if( expr->sig != NULL ) {
01116           assert( funit != NULL );
01117           if( (funit->type != FUNIT_AFUNCTION) && (funit->type != FUNIT_ANAMED_BLOCK) ) {
01118             assert( expr->elem.funit != NULL );
01119             tmp_inst = inst_link_find_by_funit( expr->elem.funit, db_list[curr_db]->inst_head, &ignore );
01120             funit_size_elements( expr->elem.funit, tmp_inst, FALSE, FALSE );
01121           }
01122           if( (expr->value->width != expr->sig->value->width) || (expr->value->value.ul == NULL) ) {
01123             assert( expr->value->value.ul == NULL );
01124             expression_create_value( expr, expr->sig->value->width, alloc );
01125           }
01126         }
01127         break;
01128 
01129       default :
01130         /*
01131          If this expression is either the root, an LHS expression or a lower-level RHS expression,
01132          get its size from the largest of its children.
01133         */
01134         if( (ESUPPL_IS_ROOT( expr->suppl ) == 1) ||
01135             (ESUPPL_IS_LHS( expr->suppl ) == 1) ||
01136             ((expr->parent->expr->op != EXP_OP_ASSIGN) &&
01137              (expr->parent->expr->op != EXP_OP_DASSIGN) &&
01138              (expr->parent->expr->op != EXP_OP_BASSIGN) &&
01139              (expr->parent->expr->op != EXP_OP_NASSIGN) &&
01140              (expr->parent->expr->op != EXP_OP_RASSIGN) &&
01141              (expr->parent->expr->op != EXP_OP_DLY_OP)) ) {
01142           if( (expr->left != NULL) && ((expr->right == NULL) || (expr->left->value->width > expr->right->value->width)) ) {
01143             largest_width = expr->left->value->width;
01144           } else if( expr->right != NULL ) {
01145             largest_width = expr->right->value->width;
01146           } else {
01147             largest_width = 1;
01148           }
01149           if( (expr->value->width != largest_width) || (expr->value->value.ul == NULL) ) {
01150             assert( expr->value->value.ul == NULL );
01151             expression_create_value( expr, largest_width, alloc );
01152           }
01153 
01154         /* If our parent is a DLY_OP, we need to get our value from the LHS of the DLY_ASSIGN expression */
01155         } else if( expr->parent->expr->op == EXP_OP_DLY_OP ) {
01156           if( (expr->parent->expr->parent->expr->left->value->width != expr->value->width) || (expr->value->value.ul == NULL) ) {
01157             assert( expr->value->value.ul == NULL );
01158             expression_create_value( expr, expr->parent->expr->parent->expr->left->value->width, alloc );
01159           }
01160 
01161         /* Otherwise, get our value from the size of the expression on the left-hand-side of the assignment */
01162         } else {
01163           if( (expr->parent->expr->left->value->width != expr->value->width) || (expr->value->value.ul == NULL) ) {
01164             assert( expr->value->value.ul == NULL );
01165             expression_create_value( expr, expr->parent->expr->left->value->width, alloc );
01166           }
01167         }
01168         break;
01169 
01170     }
01171 
01172     /* Reapply original supplemental field (preserving the owns_data bit) now that expression has been resized */
01173     new_owns_data                     = expr->value->suppl.part.owns_data;
01174     new_data_type                     = expr->value->suppl.part.data_type;
01175     expr->value->suppl.all            = old_vec_suppl;
01176     expr->value->suppl.part.owns_data = new_owns_data;
01177     expr->value->suppl.part.data_type = new_data_type;
01178 
01179   }
01180 
01181   PROFILE_END;
01182 
01183 }

void expression_set_assigned expression expr  ) 
 

Sets the expression signal supplemental field assigned bit if the given expression is an RHS of an assignment.

Checks to see if the expression is in the LHS of a BASSIGN expression tree. If it is, it sets the assigned supplemental field of the expression's signal vector to indicate the the value of this signal will come from Covered instead of the dumpfile. This is called in the bind_signal function after the expression and signal have been bound (only in parsing stage).

Parameters:
expr  Pointer to current expression to evaluate

05849   { PROFILE(EXPRESSION_SET_ASSIGNED);
05850 
05851   expression* curr;  /* Pointer to current expression */
05852 
05853   assert( expr != NULL );
05854 
05855   if( ESUPPL_IS_LHS( expr->suppl ) == 1 ) {
05856 
05857     curr = expr;
05858     while( (ESUPPL_IS_ROOT( curr->suppl ) == 0)        &&
05859            (curr->op != EXP_OP_BASSIGN)                &&
05860            (curr->op != EXP_OP_RASSIGN)                &&
05861            (curr->parent->expr->op != EXP_OP_SBIT_SEL) &&
05862            (curr->parent->expr->op != EXP_OP_MBIT_SEL) &&
05863            (curr->parent->expr->op != EXP_OP_MBIT_POS) &&
05864            (curr->parent->expr->op != EXP_OP_MBIT_NEG) ) {
05865       curr = curr->parent->expr;
05866     }
05867 
05868     /*
05869      If we are on the LHS of a BASSIGN operator, set the assigned bit to indicate that
05870      this signal will be assigned by Covered and not the dumpfile.
05871     */
05872     if( (curr->op == EXP_OP_BASSIGN) || (curr->op == EXP_OP_RASSIGN) ) {
05873       expr->sig->suppl.part.assigned = 1;
05874     }
05875 
05876   }
05877 
05878   PROFILE_END;
05879 
05880 }

void expression_set_changed expression expr  ) 
 

Sets the left/right changed expression bits for each expression in the tree.

Recursively iterates down expression tree, setting the left/right changed bits in each expression. This is necessary to get continuous assignments and FSM statements to simulate (even if their driving signals have not changed).

Parameters:
expr  Pointer to expression to set changed bits for

05889   { PROFILE(EXPRESSION_SET_CHANGED);
05890 
05891   if( expr != NULL ) {
05892 
05893     /* Set the children expressions */
05894     expression_set_changed( expr->left );
05895     expression_set_changed( expr->right );
05896 
05897     /* Now set our bits */
05898     expr->suppl.part.left_changed  = 1;
05899     expr->suppl.part.right_changed = 1;
05900 
05901   }
05902 
05903   PROFILE_END;
05904 
05905 }

void expression_set_signed expression exp  ) 
 

Sets the signed bit for all appropriate parent expressions.

Recursively sets the signed bit for all parent expressions if both the left and right expressions have the signed bit set. This function is called by the bind() function after an expression has been set to a signal.

Parameters:
exp  Pointer to current expression

00919   { PROFILE(EXPRESSION_SET_SIGNED);
00920 
00921   if( exp != NULL ) {
00922 
00923     /*
00924      If this expression is attached to a signal that has the signed bit set (which is not a bit select) or
00925      the valid left and right expressions have the signed bit set, set our is_signed bit
00926      and continue traversing up expression tree.
00927     */
00928     if( ((exp->sig != NULL) && (exp->sig->value->suppl.part.is_signed == 1) &&
00929          (exp->op != EXP_OP_SBIT_SEL)   &&
00930          (exp->op != EXP_OP_MBIT_SEL)   &&
00931          (exp->op != EXP_OP_PARAM_SBIT) &&
00932          (exp->op != EXP_OP_PARAM_MBIT)) ||
00933         ((((exp->left  != NULL) && (exp->left->value->suppl.part.is_signed  == 1)) || (exp->left  == NULL)) &&
00934          (((exp->right != NULL) && (exp->right->value->suppl.part.is_signed == 1)) || (exp->right == NULL)) &&
00935          ((exp->op == EXP_OP_ADD)      ||
00936           (exp->op == EXP_OP_SUBTRACT) ||
00937           (exp->op == EXP_OP_MULTIPLY) ||
00938           (exp->op == EXP_OP_DIVIDE)   ||
00939           (exp->op == EXP_OP_MOD)      ||
00940           (exp->op == EXP_OP_STATIC)   ||
00941           (exp->op == EXP_OP_LT)       ||
00942           (exp->op == EXP_OP_GT)       ||
00943           (exp->op == EXP_OP_LE)       ||
00944           (exp->op == EXP_OP_GE)       ||
00945           (exp->op == EXP_OP_EQ)       ||
00946           (exp->op == EXP_OP_NE))) ||
00947         (exp->value->suppl.part.is_signed == 1) ) {
00948 
00949       exp->value->suppl.part.is_signed = 1;
00950 
00951       /* If we are not the root expression, traverse up */
00952       if( ESUPPL_IS_ROOT( exp->suppl ) == 0 ) {
00953         expression_set_signed( exp->parent->expr );
00954       }
00955 
00956     }
00957     
00958   }
00959 
00960   PROFILE_END;
00961 
00962 }

void expression_set_value expression exp,
vsignal sig,
func_unit funit
 

Sets the specified expression value to the specified vector value.

Exceptions:
anonymous expression_operate_recursively expression_operate_recursively expression_operate_recursively
Sets the specified expression (if necessary) to the value of the specified signal's vector value.
Parameters:
exp  Pointer to expression to set value to
sig  Pointer to signal containing vector value to set expression to
funit  Pointer to functional unit containing expression

00825   { PROFILE(EXPRESSION_SET_VALUE);
00826   
00827   assert( exp != NULL );
00828   assert( exp->value != NULL );
00829   assert( sig != NULL );
00830   assert( sig->value != NULL );
00831 
00832   /* Set our vector type to match the signal type */
00833   exp->value->suppl.part.data_type = sig->value->suppl.part.data_type;
00834 
00835   /* If we are a SIG, PARAM or TRIGGER type, set our value to the signal's value */
00836   if( (exp->op == EXP_OP_SIG) || (exp->op == EXP_OP_PARAM) || (exp->op == EXP_OP_TRIGGER) ) {
00837 
00838     exp->value->suppl                = sig->value->suppl;
00839     exp->value->width                = sig->value->width;
00840     exp->value->value.ul             = sig->value->value.ul;
00841     exp->value->suppl.part.owns_data = 0;
00842 
00843   /* Otherwise, create our own vector to store the part select */
00844   } else {
00845 
00846     unsigned int edim      = expression_get_curr_dimension( exp );
00847     int          exp_width = vsignal_calc_width_for_expr( exp, sig );
00848     exp_dim*     dim;
00849 
00850     /* Allocate dimensional structure (if needed) and populate it with static information */
00851     if( exp->elem.dim == NULL ) {
00852       exp->elem.dim = dim = (exp_dim*)malloc_safe( sizeof( exp_dim ) );
00853     } else if( exp->suppl.part.nba == 1 ) {
00854       dim = exp->elem.dim_nba->dim;
00855     } else {
00856       dim = exp->elem.dim;
00857     }
00858       
00859     dim->curr_lsb = -1;
00860     if( sig->dim[edim].lsb < sig->dim[edim].msb ) {
00861       dim->dim_lsb = sig->dim[edim].lsb;
00862       dim->dim_be  = FALSE;
00863     } else {
00864       dim->dim_lsb = sig->dim[edim].msb;
00865       dim->dim_be  = TRUE;
00866     }
00867     dim->dim_width = exp_width;
00868     dim->last      = expression_is_last_select( exp );
00869 
00870     /* Set the expression width */
00871     switch( exp->op ) {
00872       case EXP_OP_SBIT_SEL   :
00873       case EXP_OP_PARAM_SBIT :
00874         break;
00875       case EXP_OP_MBIT_SEL   :
00876       case EXP_OP_PARAM_MBIT :
00877         {
00878           int lbit, rbit;
00879           expression_operate_recursively( exp->left,  funit, TRUE );
00880           expression_operate_recursively( exp->right, funit, TRUE );
00881           lbit = vector_to_int( exp->left->value  );
00882           rbit = vector_to_int( exp->right->value );
00883           if( lbit <= rbit ) {
00884             exp_width = ((rbit - lbit) + 1) * exp_width;
00885           } else {
00886             exp_width = ((lbit - rbit) + 1) * exp_width;
00887           }
00888         }
00889         break;
00890       case EXP_OP_MBIT_POS :
00891       case EXP_OP_MBIT_NEG :
00892       case EXP_OP_PARAM_MBIT_POS :
00893       case EXP_OP_PARAM_MBIT_NEG :
00894         expression_operate_recursively( exp->right, funit, TRUE );
00895         exp_width = vector_to_int( exp->right->value ) * exp_width;
00896         break;
00897       default :  break;
00898     }
00899 
00900     /* Allocate a vector for this expression */
00901     if( exp->value->value.ul != NULL ) {
00902       vector_dealloc_value( exp->value );
00903     }
00904     expression_create_value( exp, exp_width, TRUE );
00905 
00906   }
00907 
00908   PROFILE_END;
00909 
00910 }

char* expression_string expression exp  ) 
 

Returns user-readable version of the supplied expression.

Returns a pointer to user_msg that will contain a user-friendly string version of the given expression

Parameters:
exp  Pointer to expression to display

01845   { PROFILE(EXPRESSION_STRING);
01846 
01847   unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "%d (%s line %d)", exp->id, expression_string_op( exp->op ), exp->line );
01848   assert( rv < USER_MSG_LENGTH );
01849 
01850   PROFILE_END;
01851 
01852   return( user_msg );
01853 
01854 }

const char* expression_string_op int  op  ) 
 

Returns user-readable name of specified expression operation.

Returns:
Returns a non-writable string that contains the user-readable name of the specified expression operation.
Parameters:
op  Expression operation to get string representation of

01829   { PROFILE(EXPRESSION_STRING_OP);
01830 
01831   assert( (op >= 0) && (op < EXP_OP_NUM) );
01832 
01833   PROFILE_END;
01834 
01835   return( exp_op_info[op].name );
01836 
01837 }


Generated on Wed Jun 17 22:19:21 2009 for Covered by doxygen 1.3.4