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

/Users/trevorw/projects/release/covered-0.7.4/src/binding.c File Reference


Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
3/4/2002
Binding
When a input, output, inout, reg, wire, etc. is parsed in a module a new signal structure is created and is placed into the current module's signal list. However, the expression list of the newly created signal is initially empty (because we have not encountered any expressions that use the signal yet). Each signal contains a list of expressions that the signal is a part of so that when the signal changes its value during simulation time, it can notify the expressions that it is a part of that they need to be re-evaluated.
Additionally, the expression structure contains a pointer to the signal from which it receives its value. However, not all expressions point to signals. Only the expressions which have an operation type of EXP_OP_SIG, EXP_OP_SBIT_SEL, EXP_OP_MBIT_SEL, and EXP_OP_FUNC_CALL have pointers to signals. These pointers are used for quick retrieval of the signal name when outputting expressions.
Because both signals and expressions point to each other, we say that signals and expressions need to be bound to each other. The process of binding takes place after all design file parsing has been completed, allowing an expression to be bound to a signal elsewhere in the design. Binding is performed twice at this point in the score command (occurs once for the merge and report commands). The first binding pass binds all expressions to local signals/parameters. This local binding is required to allow parameters and constant function calls in parameter assignments to be calculated correctly. As each binding is performed, it is removed from the list of all bindings that need to be performed for the design. After the first binding pass is performed, all parameters are resolved for their values and all generated logic is created, after which all other expressions that still need to bound are handled.
Implicit Signal Creation
In several Verilog simulators, the automatic creation of one-bit wires is allowed. These signals are considered "automatically created" because they are not declared in either the port list or the wire list for its particular module. Therefore, when the binding process occurs and a signal structure has not been created for a used signal (because the signal was not declared in the port list or wire list), the bind_signal function needs to do one of the following:
  1. If the signal name expresses a signal name that will be local to the current module (i.e., there aren't any periods in the signal name), automatically create a one-bit signal for the missing signal and bind this new signal to the expression that uses the implicit signal.
  2. If the signal name expresses a signal name that will be remote to the current module (i.e., if there are periods in the signal name), generate an error message to the user about using a bad hierarchical reference.

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "binding.h"
#include "defines.h"
#include "expr.h"
#include "func_unit.h"
#include "gen_item.h"
#include "instance.h"
#include "iter.h"
#include "link.h"
#include "obfuscate.h"
#include "ovl.h"
#include "param.h"
#include "scope.h"
#include "statement.h"
#include "stmt_blk.h"
#include "util.h"
#include "vector.h"
#include "vsignal.h"

Functions

void bind_add (int type, const char *name, expression *exp, func_unit *funit)
 Adds vsignal and expression to binding list.

void bind_append_fsm_expr (expression *fsm_exp, const expression *exp, const func_unit *curr_funit)
 Appends an FSM expression to a matching expression binding structure.

void bind_display_list ()
void bind_remove (int id, bool clear_assigned)
 Removes the expression with ID of id from binding list.

char * bind_find_sig_name (const expression *exp)
 Searches current binding list for the signal name associated with the given expression.

bool bind_param (const char *name, expression *exp, func_unit *funit_exp, int exp_line, bool bind_locally)
bool bind_signal (char *name, expression *exp, func_unit *funit_exp, bool fsm_bind, bool cdd_reading, bool clear_assigned, int exp_line, bool bind_locally)
 Binds a signal to an expression.

void bind_task_function_ports (expression *expr, func_unit *funit, char *name, int *order, func_unit *funit_exp)
bool bind_task_function_namedblock (int type, char *name, expression *exp, func_unit *funit_exp, bool cdd_reading, int exp_line, bool bind_locally)
void bind_perform (bool cdd_reading, int pass)
 Performs vsignal/expression bind (performed after parse completed).

void bind_dealloc ()
 Deallocates memory used for binding.


Variables

db ** db_list
unsigned int curr_db
funit_linkfunit_head
char user_msg [USER_MSG_LENGTH]
bool debug_mode
exp_bindeb_head
exp_bindeb_tail


Function Documentation

void bind_add int  type,
const char *  name,
expression exp,
func_unit funit
 

Adds vsignal and expression to binding list.

Adds the specified signal/function/task and expression to the bindings linked list. This bindings list will be handled after all input Verilog has been parsed.

Parameters:
type  Type of thing being bound with the specified expression (0=signal, 1=functional unit)
name  Signal/Function/Task scope to bind
exp  Expression ID to bind
funit  Pointer to module containing specified expression

00125   { PROFILE(BIND_ADD);
00126   
00127   exp_bind* eb;   /* Temporary pointer to signal/expressing binding */
00128 
00129   assert( exp != NULL );
00130   
00131   /* Create new signal/expression binding */
00132   eb                 = (exp_bind *)malloc_safe( sizeof( exp_bind ) );
00133   eb->type           = type;
00134   eb->name           = strdup_safe( name );
00135   eb->clear_assigned = 0;
00136   eb->line           = exp->line;
00137   eb->funit          = funit;
00138   eb->exp            = exp;
00139   eb->fsm            = NULL;
00140   eb->next           = NULL;
00141   
00142   /* Add new signal/expression binding to linked list */
00143   if( eb_head == NULL ) {
00144     eb_head = eb_tail = eb;
00145   } else {
00146     eb_tail->next = eb;
00147     eb_tail       = eb;
00148   }
00149 
00150   PROFILE_END;
00151   
00152 }

void bind_append_fsm_expr expression fsm_exp,
const expression exp,
const func_unit curr_funit
 

Appends an FSM expression to a matching expression binding structure.

Searches the expression binding list for the entry that matches the given exp and curr_funit parameters. When the entry is found, the FSM expression is added to the exp_bind structure to be sized when the expression is bound.

Parameters:
fsm_exp  Expression pertaining to an FSM input state that needs to be sized when its associated expression is bound to its signal
exp  Expression to match
curr_funit  Functional unit that the FSM expression resides in (this will be the same functional unit as the expression functional unit)

00165   { PROFILE(BIND_APPEND_FSM_EXPR);
00166 
00167   exp_bind* curr;
00168 
00169   curr = eb_head;
00170   while( (curr != NULL) && ((exp != curr->exp) || (curr_funit != curr->funit)) ) {
00171     curr = curr->next;
00172   }
00173 
00174   assert( curr != NULL );
00175 
00176   curr->fsm = fsm_exp;
00177 
00178   PROFILE_END;
00179 
00180 }

void bind_dealloc  ) 
 

Deallocates memory used for binding.

Deallocates all memory used for the storage of the binding list.

00923                     { PROFILE(BIND_DEALLOC);
00924 
00925   exp_bind* tmp;  /* Temporary binding pointer */
00926 
00927   while( eb_head != NULL ) {
00928 
00929     tmp     = eb_head;
00930     eb_head = tmp->next;
00931 
00932     /* Deallocate the name, if specified */
00933     if( tmp->name != NULL ) {
00934       free_safe( tmp->name, (strlen( tmp->name ) + 1) );
00935     }
00936 
00937     /* Deallocate this structure */
00938     free_safe( tmp, sizeof( exp_bind ) );
00939 
00940   }
00941 
00942   /* Reset the head and tail pointers */
00943   eb_head = eb_tail = NULL;
00944 
00945   PROFILE_END;
00946 
00947 }

void bind_display_list  ) 
 

Displays to standard output the current state of the binding list (debug purposes only).

00185                          {
00186 
00187   exp_bind* curr;  /* Pointer to current expression binding */
00188 
00189   curr = eb_head;
00190  
00191   printf( "Expression binding list:\n" );
00192 
00193   while( curr != NULL ) {
00194 
00195     switch( curr->type ) {
00196       case FUNIT_AFUNCTION :
00197       case FUNIT_FUNCTION :
00198         printf( "  Expr: %d, %s, line %d;  Functional Unit: %s;  Function: %s\n",
00199                 curr->exp->id, expression_string_op( curr->exp->op ), curr->exp->line,
00200                 obf_funit( curr->funit->name ), obf_sig( curr->name ) );
00201         break;
00202       case FUNIT_ATASK :
00203       case FUNIT_TASK :
00204         printf( "  Expr: %d, %s, line %d;  Functional Unit: %s;  Task: %s\n",
00205                 curr->exp->id, expression_string_op( curr->exp->op ), curr->exp->line,
00206                 obf_funit( curr->funit->name ), obf_sig( curr->name ) );
00207         break;
00208       case FUNIT_ANAMED_BLOCK :
00209       case FUNIT_NAMED_BLOCK :
00210         printf( "  Expr: %d, %s, line %d;  Functional Unit: %s;  Named Block: %s\n",
00211                 curr->exp->id, expression_string_op( curr->exp->op ), curr->exp->line,
00212                 obf_funit( curr->funit->name ), obf_sig( curr->name ) );
00213         break;
00214       case 0 :
00215         if( curr->clear_assigned > 0 ) {
00216           printf( "  Signal to be cleared: %s\n", obf_sig( curr->name ) );
00217         } else {
00218           printf( "  Expr: %d, %s, line %d;  Functional Unit: %s;  Signal: %s\n",
00219                   curr->exp->id, expression_string_op( curr->exp->op ), curr->exp->line,
00220                   obf_funit( curr->funit->name ), obf_sig( curr->name ) );
00221         }
00222         break;
00223       default :  break;
00224     }
00225 
00226     curr = curr->next;
00227 
00228   }
00229 
00230 }

char* bind_find_sig_name const expression exp  ) 
 

Searches current binding list for the signal name associated with the given expression.

Returns:
Returns the name of the signal to be bound with the given expression (if one exists); otherwise, returns NULL if no match was found.
Parameters:
exp  Pointer to expression to search for

00297   { PROFILE(BIND_FIND_SIG_NAME);
00298 
00299   exp_bind*  curr;         /* Pointer to current exp_bind link */
00300   vsignal*   found_sig;    /* Placeholder */
00301   func_unit* found_funit;  /* Specifies the functional unit containing this signal */
00302   char*      name = NULL;  /* Specifies the signal name relative to its parent module */
00303   char*      front;        /* Front part of functional unit hierarchy */
00304   char*      rest;         /* Rest of functional unit hierarchy (minus front) */
00305  
00306   /* Find matching binding element that matches the given expression */
00307   curr = eb_head;
00308   while( (curr != NULL) && (curr->exp != exp) ) {
00309     curr = curr->next;
00310   }
00311 
00312   /*
00313    If we found the matching expression, find the signal and construct its hierarchical pathname
00314    relative to its parent module.
00315   */
00316   if( curr != NULL ) {
00317     if( scope_find_signal( curr->name, curr->funit, &found_sig, &found_funit, -1 ) ) {
00318       if( funit_get_curr_module_safe( curr->funit ) == funit_get_curr_module_safe( found_funit ) ) {
00319         front = strdup_safe( found_funit->name );
00320         rest  = strdup_safe( found_funit->name );
00321         scope_extract_front( found_funit->name, front, rest );
00322         if( rest[0] != '\0' ) {
00323           unsigned int sig_size = strlen( curr->name ) + strlen( rest ) + 2;
00324           unsigned int rv;
00325           name = (char*)malloc_safe( sig_size );
00326           rv = snprintf( name, sig_size, "%s.%s", rest, curr->name );
00327           assert( rv < sig_size );
00328         }
00329         free_safe( front, (strlen( found_funit->name ) + 1) );
00330         free_safe( rest, (strlen( found_funit->name ) + 1) );
00331       }
00332     }
00333     if( name == NULL ) {
00334       name = strdup_safe( curr->name );
00335     }
00336   }
00337 
00338   PROFILE_END;
00339 
00340   return( name );
00341 
00342 }

bool bind_param const char *  name,
expression exp,
func_unit funit_exp,
int  exp_line,
bool  bind_locally
[static]
 

Returns:
Returns TRUE if the given name referred to a parameter value that was bound; otherwise, returns FALSE.
Attempts to bind the specified expression to a parameter in the design. If binding is successful, returns TRUE; otherwise, returns FALSE.
Parameters:
name  Name of parameter to bind to
exp  Pointer to expression to bind parameter to
funit_exp  Pointer to functional unit containing exp
exp_line  Line number of given expression to bind (for error output purposes only)
bind_locally  Set to TRUE if we are attempting to bind locally

00357   { PROFILE(BIND_PARAM);
00358 
00359   bool       retval = FALSE;  /* Return value for this function */
00360   mod_parm*  found_parm;      /* Pointer to found parameter in design for the given name */
00361   func_unit* found_funit;     /* Pointer to found functional unit containing given signal */
00362 
00363   /* Skip parameter binding if the name is not local and we are binding locally */
00364   if( scope_local( name ) || !bind_locally ) {
00365 
00366     /* Search for specified parameter in current functional unit */
00367     if( scope_find_param( name, funit_exp, &found_parm, &found_funit, exp_line ) ) {
00368 
00369       /* Swap operation type */
00370       switch( exp->op ) {
00371         case EXP_OP_SIG      :  exp->op = EXP_OP_PARAM;           break;
00372         case EXP_OP_SBIT_SEL :  exp->op = EXP_OP_PARAM_SBIT;      break;
00373         case EXP_OP_MBIT_SEL :  exp->op = EXP_OP_PARAM_MBIT;      break;
00374         case EXP_OP_MBIT_POS :  exp->op = EXP_OP_PARAM_MBIT_POS;  break;
00375         case EXP_OP_MBIT_NEG :  exp->op = EXP_OP_PARAM_MBIT_NEG;  break;
00376         default :
00377           assert( (exp->op == EXP_OP_SIG)      ||
00378                   (exp->op == EXP_OP_SBIT_SEL) ||
00379                   (exp->op == EXP_OP_MBIT_SEL) ||
00380                   (exp->op == EXP_OP_MBIT_POS) ||
00381                   (exp->op == EXP_OP_MBIT_NEG) );
00382           break;
00383       }
00384 
00385       /* Link the expression to the module parameter */
00386       exp_link_add( exp, &(found_parm->exp_head), &(found_parm->exp_tail) );
00387 
00388       /* Indicate that we have successfully bound */
00389       retval = TRUE;
00390 
00391     }
00392 
00393   }
00394 
00395   PROFILE_END;
00396 
00397   return( retval );
00398 
00399 }

void bind_perform bool  cdd_reading,
int  pass
 

Performs vsignal/expression bind (performed after parse completed).

Exceptions:
anonymous Throw param_resolve bind_signal generate_resolve bind_task_function_namedblock bind_task_function_namedblock
In the process of binding, we go through each element of the binding list, finding the signal to be bound in the specified tree, adding the expression to the signal's expression pointer list, and setting the expression vector pointer to point to the signal vector.
Parameters:
cdd_reading  Set to TRUE if we are binding after reading the CDD file; otherwise, set to FALSE
pass  Specifies the starting pass to perform (setting this to 1 will bypass resolutions)

00765   { PROFILE(BIND_PERFORM);
00766   
00767   exp_bind*  curr_eb;   /* Pointer to current expression bind structure */
00768   int        id;        /* Current expression id -- used for removal */
00769   bool       bound;     /* Specifies if the current expression was successfully bound or not */
00770   statement* tmp_stmt;  /* Pointer to temporary statement */
00771 
00772   Try {
00773 
00774     /* Make three passes through binding list, 0=local signal/param bindings, 1=remote signal/param bindings */
00775     for( ; pass<2; pass++ ) {
00776 
00777       curr_eb = eb_head;
00778       while( curr_eb != NULL ) {
00779 
00780         /* Figure out ID to clear from the binding list after the bind occurs */
00781         if( curr_eb->clear_assigned == 0 ) {
00782           id = curr_eb->exp->id;
00783         } else {
00784           id = curr_eb->clear_assigned;
00785         }
00786 
00787         /* If the expression has already been bound, do not attempt to do it again */
00788         if( (curr_eb->exp != NULL) && (curr_eb->exp->name != NULL) ) {
00789 
00790           bound = TRUE;
00791 
00792         } else {
00793 
00794           /* Handle signal/parameter binding */
00795           if( curr_eb->type == 0 ) {
00796 
00797             /* Attempt to bind the expression to a parameter; otherwise, bind to a signal */
00798             if( !(bound = bind_param( curr_eb->name, curr_eb->exp, curr_eb->funit, curr_eb->line, (pass == 0) )) ) {
00799               bound = bind_signal( curr_eb->name, curr_eb->exp, curr_eb->funit, FALSE, cdd_reading,
00800                                    (curr_eb->clear_assigned > 0), curr_eb->line, (pass == 0) );
00801             }
00802 
00803             /* If an FSM expression is attached, size it now */
00804             if( curr_eb->fsm != NULL ) {
00805               curr_eb->fsm->value = vector_create( curr_eb->exp->value->width, VTYPE_EXP, VDATA_UL, TRUE );
00806             }
00807 
00808           /* Otherwise, handle disable binding */
00809           } else if( curr_eb->type == 1 ) {
00810 
00811             /* Attempt to bind a named block -- if unsuccessful, attempt to bind with a task */
00812             if( !(bound = bind_task_function_namedblock( FUNIT_NAMED_BLOCK, curr_eb->name, curr_eb->exp, curr_eb->funit,
00813                                                          cdd_reading, curr_eb->line, (pass == 0) )) ) {
00814               bound = bind_task_function_namedblock( FUNIT_TASK, curr_eb->name, curr_eb->exp, curr_eb->funit,
00815                                                      cdd_reading, curr_eb->line, (pass == 0) );
00816             }
00817 
00818           /* Otherwise, handle function/task binding */
00819           } else {
00820 
00821             /*
00822              Bind the expression to the task/function.  If it is unsuccessful, we need to remove the statement
00823              that this expression is a part of.
00824             */
00825             bound = bind_task_function_namedblock( curr_eb->type, curr_eb->name, curr_eb->exp, curr_eb->funit,
00826                                                    cdd_reading, curr_eb->line, (pass == 0) );
00827 
00828           }
00829 
00830           /* If we have bound successfully, copy the name of this exp_bind to the expression */
00831           if( bound && (curr_eb->exp != NULL) ) {
00832             curr_eb->exp->name = strdup_safe( curr_eb->name );
00833           }
00834 
00835         }
00836 
00837         /*
00838          If the expression was unable to be bound, put its statement block in a list to be removed after
00839          binding has been completed.
00840         */
00841         if( !bound && (curr_eb->clear_assigned == 0) && (pass == 1) ) {
00842           if( (tmp_stmt = expression_get_root_statement( curr_eb->exp )) != NULL ) {
00843 #ifdef DEBUG_MODE
00844             if( debug_mode ) {
00845               unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Removing statement block containing line %d in file \"%s\", because it was unbindable",
00846                                           curr_eb->exp->line, obf_file( curr_eb->funit->filename ) );
00847               assert( rv < USER_MSG_LENGTH );
00848               print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00849             }
00850 #endif        
00851             stmt_blk_add_to_remove_list( tmp_stmt );
00852           }
00853         }
00854 
00855         curr_eb = curr_eb->next;
00856 
00857         /* Remove this from the binding list */
00858         if( bound ) {
00859           bind_remove( id, FALSE );
00860         }
00861 
00862       }
00863 
00864 #ifndef VPI_ONLY
00865       /* If we are in parse mode, resolve all parameters and arrays of instances now */
00866       if( !cdd_reading && (pass == 0) ) {
00867         inst_link* instl;
00868 #ifdef DEBUG_MODE
00869         if( debug_mode ) {
00870           print_output( "Resolving parameters...", DEBUG, __FILE__, __LINE__ );
00871         }
00872 #endif
00873         instl = db_list[curr_db]->inst_head;
00874         while( instl != NULL ) {
00875           param_resolve( instl->inst );
00876           instl = instl->next;
00877         }
00878 #ifdef DEBUG_MODE
00879         if( debug_mode ) {
00880           print_output( "Resolving generate statements...", DEBUG, __FILE__, __LINE__ );
00881         }
00882 #endif
00883         instl = db_list[curr_db]->inst_head;
00884         while( instl != NULL ) {
00885           generate_resolve( instl->inst );
00886           instl = instl->next;
00887         }
00888 #ifdef DEBUG_MODE
00889         if( debug_mode ) {
00890           print_output( "Resolving arrays of instances...", DEBUG, __FILE__, __LINE__ );
00891         }
00892 #endif
00893         instl = db_list[curr_db]->inst_head;
00894         while( instl != NULL ) {
00895           instance_resolve( instl->inst );
00896           instl = instl->next;
00897         }
00898       }
00899 #endif
00900 
00901     }
00902 
00903   } Catch_anonymous {
00904     exp_bind* tmp_eb;
00905     curr_eb = eb_head;
00906     while( curr_eb != NULL ) {
00907       tmp_eb  = curr_eb;
00908       curr_eb = curr_eb->next;
00909       free_safe( tmp_eb->name, (strlen( tmp_eb->name ) + 1) );
00910       free_safe( tmp_eb, sizeof( exp_bind ) );
00911     }
00912     eb_head = eb_tail = NULL;
00913     Throw 0;
00914   }
00915 
00916   PROFILE_END;
00917 
00918 }

void bind_remove int  id,
bool  clear_assigned
 

Removes the expression with ID of id from binding list.

Removes the binding containing the expression ID of id. This needs to be called before an expression is removed.

Parameters:
id  Expression ID of binding to remove
clear_assigned  If set to TRUE, clears the assigned bit in the specified expression

00239   { PROFILE(BIND_REMOVE);
00240 
00241   exp_bind* curr;  /* Pointer to current exp_bind link */
00242   exp_bind* last;  /* Pointer to last exp_bind link examined */
00243 
00244   curr = eb_head;
00245   last = eb_head;
00246 
00247   while( curr != NULL ) {
00248 
00249     if( ((curr->exp != NULL) && (curr->exp->id == id)) || (curr->clear_assigned == id) ) {
00250       
00251       if( clear_assigned ) {
00252 
00253         curr->clear_assigned = id;
00254         curr->exp            = NULL;
00255 
00256       } else {
00257 
00258         /* Remove this binding element */
00259         if( (curr == eb_head) && (curr == eb_tail) ) {
00260           eb_head = eb_tail = NULL;
00261         } else if( curr == eb_head ) {
00262           eb_head = eb_head->next;
00263         } else if( curr == eb_tail ) {
00264           eb_tail       = last;
00265           eb_tail->next = NULL;
00266         } else {
00267           last->next = curr->next;
00268         }
00269 
00270         /* Now free the binding element memory */
00271         free_safe( curr->name, (strlen( curr->name ) + 1) );
00272         free_safe( curr, sizeof( exp_bind ) );
00273 
00274       }
00275 
00276       curr = NULL;
00277       
00278     } else {
00279 
00280       last = curr;
00281       curr = curr->next;
00282 
00283     }
00284 
00285   }
00286 
00287   PROFILE_END;
00288 
00289 }

bool bind_signal char *  name,
expression exp,
func_unit funit_exp,
bool  fsm_bind,
bool  cdd_reading,
bool  clear_assigned,
int  exp_line,
bool  bind_locally
 

Binds a signal to an expression.

Returns:
Returns TRUE if bind occurred successfully; otherwise, returns FALSE.
Exceptions:
anonymous expression_set_value
Performs a binding of an expression and signal based on the name of the signal. Looks up signal name in the specified functional unit and sets the expression and signal to point to each other. If the signal is unused, the bind does not occur and the function returns a value of FALSE. If the signal does not exist, it is considered to be an implicit signal and a 1-bit signal is created.
Parameters:
name  String name of signal to bind to specified expression
exp  Pointer to expression to bind
funit_exp  Pointer to functional unit containing expression
fsm_bind  If set to TRUE, handling binding for FSM binding
cdd_reading  If set to TRUE, specifies that we are binding after reading a design from a CDD file (instead of the design files)
clear_assigned  If set to TRUE, clears signal assigned bit
exp_line  Line of specified expression (when expression is NULL)
bind_locally  If TRUE, only search for specified signal within the same functional unit as this expression

00421   { PROFILE(BIND_SIGNAL);
00422 
00423   bool         retval = TRUE;  /* Return value for this function */
00424   vsignal*     found_sig;      /* Pointer to found signal in design for the given name */
00425   func_unit*   found_funit;    /* Pointer to found functional unit containing given signal */
00426   statement*   stmt;           /* Pointer to root statement for the given expression */
00427   exp_link*    expl;           /* Pointer to current expression link */
00428   unsigned int rv;             /* Return value from snprintf calls */
00429 
00430   /* Skip signal binding if the name is not local and we are binding locally */
00431   if( scope_local( name ) || !bind_locally || (!clear_assigned && (exp->op == EXP_OP_PASSIGN)) ) {
00432 
00433     /* Search for specified signal in current functional unit */
00434     if( !scope_find_signal( name, funit_exp, &found_sig, &found_funit, exp_line ) ) {
00435 
00436       /* If we are binding an FSM, output an error message */
00437       if( fsm_bind ) {
00438         rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to find specified FSM signal \"%s\" in module \"%s\" in file %s",
00439                        obf_sig( name ), obf_funit( funit_exp->name ), obf_file( funit_exp->filename ) );
00440         assert( rv < USER_MSG_LENGTH );
00441         print_output( user_msg, FATAL, __FILE__, __LINE__ );
00442         retval = FALSE;
00443 
00444       /* Otherwise, implicitly create the signal and bind to it if the signal exists on the LHS of the equation */
00445       } else if( ESUPPL_IS_LHS( exp->suppl ) == 1 ) {
00446         assert( exp != NULL );
00447         rv = snprintf( user_msg, USER_MSG_LENGTH, "Implicit declaration of signal \"%s\", creating 1-bit version of signal", obf_sig( name ) );
00448         assert( rv < USER_MSG_LENGTH );
00449         print_output( user_msg, WARNING, __FILE__, __LINE__ );
00450         rv = snprintf( user_msg, USER_MSG_LENGTH, "module \"%s\", file \"%s\", line %d",
00451                        obf_funit( funit_exp->name ), obf_file( funit_exp->filename ), exp_line );
00452         assert( rv < USER_MSG_LENGTH );
00453         print_output( user_msg, WARNING_WRAP, __FILE__, __LINE__ );
00454         found_sig = vsignal_create( name, SSUPPL_TYPE_IMPLICIT, 1, exp->line, ((exp->col >> 16) & 0xffff) );
00455         found_sig->pdim_num   = 1;
00456         found_sig->dim        = (dim_range*)malloc_safe( sizeof( dim_range ) * 1 );
00457         found_sig->dim[0].msb = 0;
00458         found_sig->dim[0].lsb = 0;
00459         sig_link_add( found_sig, &(funit_exp->sig_head), &(funit_exp->sig_tail) );
00460 
00461       /* Otherwise, don't attempt to bind the signal */
00462       } else {
00463         retval = FALSE;
00464       }
00465 
00466     } else {
00467 
00468       /* If the found signal is not handled, do not attempt to bind to it */
00469       if( found_sig->suppl.part.not_handled == 1 ) {
00470         retval = FALSE;
00471       }
00472 
00473     }
00474 
00475     if( retval ) {
00476 
00477       /* Bind signal and expression if we are not clearing or this is an MBA */
00478       if( !clear_assigned ) {
00479 
00480         /* Add expression to signal expression list */
00481         exp_link_add( exp, &(found_sig->exp_head), &(found_sig->exp_tail) );
00482 
00483         /* Set expression to point at signal */
00484         exp->sig = found_sig;
00485 
00486         /* If this is a port assignment, we need to link the expression and signal together immediately */
00487         if( exp->op == EXP_OP_PASSIGN ) {
00488           vector_dealloc( exp->value );
00489           exp->suppl.part.owns_vec = 0;
00490           exp->value = found_sig->value;
00491         }
00492 
00493         if( ((exp->op == EXP_OP_SIG)            ||
00494              (exp->op == EXP_OP_SBIT_SEL)       ||
00495              (exp->op == EXP_OP_MBIT_SEL)       ||
00496              (exp->op == EXP_OP_MBIT_POS)       ||
00497              (exp->op == EXP_OP_MBIT_NEG)       ||
00498              (exp->op == EXP_OP_PARAM)          ||
00499              (exp->op == EXP_OP_PARAM_SBIT)     ||
00500              (exp->op == EXP_OP_PARAM_MBIT)     ||
00501              (exp->op == EXP_OP_PARAM_MBIT_POS) ||
00502              (exp->op == EXP_OP_PARAM_MBIT_NEG) ||
00503              (exp->op == EXP_OP_TRIGGER)) &&
00504             (cdd_reading || (found_sig->suppl.part.type == SSUPPL_TYPE_GENVAR)) ) {
00505           expression_set_value( exp, found_sig, funit_exp );
00506         }
00507 
00508         /*
00509          Create a non-blocking assignment handler for the given expression if the attached signal is a memory
00510          and the expression is assignable on the LHS of a non-blocking assignment operator.  Only perform this
00511          if we are reading from the CDD file and binding.
00512         */
00513         if( cdd_reading && (found_sig->suppl.part.type == SSUPPL_TYPE_MEM) ) {
00514           expression* nba_exp;
00515           if( (nba_exp = expression_is_nba_lhs( exp )) != NULL ) {
00516             expression_create_nba( exp, found_sig, nba_exp->right->value );
00517           }
00518         }
00519 
00520       }
00521 
00522       if( !cdd_reading ) {
00523 
00524         /* Check to see if this signal should be assigned by Covered or the dumpfile */
00525         if( clear_assigned ) {
00526           found_sig->suppl.part.assigned = 0;
00527         }
00528 
00529         if( !clear_assigned &&
00530             ((exp->op == EXP_OP_SIG)      ||
00531              (exp->op == EXP_OP_SBIT_SEL) ||
00532              (exp->op == EXP_OP_MBIT_SEL) ||
00533              (exp->op == EXP_OP_MBIT_POS) ||
00534              (exp->op == EXP_OP_MBIT_NEG)) &&
00535             !ovl_is_assertion_module( funit_exp ) ) {
00536           expression_set_assigned( exp );
00537         }
00538 
00539         /* Set signed bits */
00540         if( !clear_assigned ) {
00541           expression_set_signed( exp );
00542         }
00543 
00544         /*
00545          If the signal is found for the given expression but the signal is marked as "must be assigned" but is also marked as
00546          "won't be assigned", we need to remove all statement blocks that contain this signal from coverage consideration.
00547         */
00548         if( (found_sig->suppl.part.assigned == 0) && (found_sig->suppl.part.mba == 1) ) {
00549           expl = found_sig->exp_head;
00550           while( expl != NULL ) {
00551             if( (stmt = expression_get_root_statement( expl->exp )) != NULL ) {
00552 #ifdef DEBUG_MODE
00553               if( debug_mode ) {
00554                 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Removing statement block %d, line %d because it needed to be assigned but would not be",
00555                                             stmt->exp->id, stmt->exp->line );
00556                 assert( rv < USER_MSG_LENGTH );
00557                 print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00558               }
00559 #endif
00560               stmt_blk_add_to_remove_list( stmt );
00561             }
00562             expl = expl->next;
00563           }
00564         }
00565 
00566       }
00567 
00568     }
00569 
00570   } else {
00571 
00572     retval = FALSE;
00573 
00574   }
00575 
00576   PROFILE_END;
00577 
00578   return( retval );
00579 
00580 }

bool bind_task_function_namedblock int  type,
char *  name,
expression exp,
func_unit funit_exp,
bool  cdd_reading,
int  exp_line,
bool  bind_locally
[static]
 

Returns:
Returns TRUE if there were no errors in binding the specified expression to the needed functional unit; otherwise, returns FALSE to indicate that we had an error.
Exceptions:
anonymous Throw
Binds an expression to a function/task/named block.
Parameters:
type  Type of functional unit to bind
name  Name of functional unit to bind
exp  Pointer to expression containing FUNC_CALL/TASK_CALL operation type to bind
funit_exp  Pointer to functional unit containing exp
cdd_reading  Set to TRUE when we are reading from the CDD file (FALSE when parsing)
exp_line  Line number of expression that is being bound (used when exp is NULL)
bind_locally  If set to TRUE, only attempt to bind a task/function local to the expression functional unit

00681   { PROFILE(BIND_TASK_FUNCTION_NAMEDBLOCK);
00682 
00683   bool       retval = FALSE;  /* Return value for this function */
00684   sig_link*  sigl;            /* Temporary signal link holder */
00685   func_unit* found_funit;     /* Pointer to found task/function functional unit */
00686   char       rest[4096];      /* Temporary string */
00687   char       back[4096];      /* Temporary string */
00688   int        port_order;      /* Port order value */
00689   int        port_cnt;        /* Number of ports in the found function/task's port list */
00690 
00691   assert( (type == FUNIT_FUNCTION) || (type == FUNIT_TASK) || (type == FUNIT_NAMED_BLOCK) || (type == FUNIT_ANAMED_BLOCK) );
00692 
00693   /* Don't continue if the name is not local and we are told to bind locally */
00694   if( scope_local( name ) || !bind_locally ) {
00695 
00696     if( scope_find_task_function_namedblock( name, type, funit_exp, &found_funit, exp_line, !bind_locally, 
00697                                              ((exp->op != EXP_OP_NB_CALL) && (exp->op != EXP_OP_FORK)) ) ) {
00698 
00699       exp->elem.funit      = found_funit;
00700       exp->suppl.part.type = ETYPE_FUNIT;
00701       retval = (found_funit->type != FUNIT_NO_SCORE);
00702 
00703       if( retval ) {
00704 
00705         /* If this is a function, bind the return value signal */
00706         if( type == FUNIT_FUNCTION ) {
00707 
00708           scope_extract_back( found_funit->name, back, rest );
00709           sigl = sig_link_find( back, found_funit->sig_head );
00710 
00711           assert( sigl != NULL );
00712 
00713           /* Add expression to signal expression list */
00714           exp_link_add( exp, &(sigl->sig->exp_head), &(sigl->sig->exp_tail) );
00715 
00716           /* Set expression to point at signal */
00717           exp->sig = sigl->sig;
00718 
00719           /* Make sure that our vector type matches that of the found signal */
00720           exp->value->suppl.part.data_type = sigl->sig->value->suppl.part.data_type;
00721 
00722         }
00723 
00724         /* If this is a function or task, bind the ports as well */
00725         if( ((type == FUNIT_FUNCTION) || (type == FUNIT_TASK)) && !cdd_reading ) {
00726 
00727           /* First, bind the ports */
00728           port_order = 0;
00729           bind_task_function_ports( exp->left, found_funit, name, &port_order, funit_exp );
00730 
00731           /* Check to see if the call port count matches the actual port count */
00732           if( (port_cnt = funit_get_port_count( found_funit )) != port_order ) {
00733             unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Number of arguments in %s call (%d) does not match its %s port list (%d), file %s, line %d",
00734                                         get_funit_type( type ), port_order, get_funit_type( type ), port_cnt, obf_file( funit_exp->filename ), exp->line );
00735             assert( rv < USER_MSG_LENGTH );
00736             print_output( user_msg, FATAL, __FILE__, __LINE__ );
00737             Throw 0;
00738           }
00739 
00740         }
00741 
00742       }
00743 
00744     }
00745 
00746   }
00747 
00748   PROFILE_END;
00749 
00750   return( retval );
00751 
00752 }

void bind_task_function_ports expression expr,
func_unit funit,
char *  name,
int *  order,
func_unit funit_exp
[static]
 

Binds a given task/function call port parameter to the matching signal in the specified task/function.

Parameters:
expr  Pointer to port expression to potentially bind to the specified port
funit  Pointer to task/function to bind port list to
name  Hierachical name of function to bind port list to
order  Tracks the port order for the current task/function call parameter
funit_exp  Pointer to functional unit containing the given expression

00592   { PROFILE(BIND_TASK_FUNCTION_PORTS);
00593 
00594   sig_link* sigl;            /* Pointer to current signal link to examine */
00595   int       i;               /* Loop iterator */
00596   bool      found;           /* Specifies if we have found a matching port */
00597   char      sig_name[4096];  /* Hierarchical path to matched port signal */
00598 
00599   assert( funit != NULL );
00600 
00601   if( expr != NULL ) {
00602 
00603     /* If the expression is a list, traverse left and right expression trees */
00604     if( expr->op == EXP_OP_PLIST ) {
00605 
00606       bind_task_function_ports( expr->left,  funit, name, order, funit_exp );
00607       bind_task_function_ports( expr->right, funit, name, order, funit_exp );
00608 
00609     /* Otherwise, we have found an expression to bind to a port */
00610     } else {
00611 
00612       assert( expr->op == EXP_OP_PASSIGN );
00613 
00614       /* Find the port that matches our order */
00615       found = FALSE;
00616       i     = 0;
00617       sigl  = funit->sig_head;
00618       while( (sigl != NULL) && !found ) {
00619         if( (sigl->sig->suppl.part.type == SSUPPL_TYPE_INPUT_NET)  ||
00620             (sigl->sig->suppl.part.type == SSUPPL_TYPE_INPUT_REG)  ||
00621             (sigl->sig->suppl.part.type == SSUPPL_TYPE_OUTPUT_NET) ||
00622             (sigl->sig->suppl.part.type == SSUPPL_TYPE_OUTPUT_REG) ||
00623             (sigl->sig->suppl.part.type == SSUPPL_TYPE_INOUT_NET)  ||
00624             (sigl->sig->suppl.part.type == SSUPPL_TYPE_INOUT_REG) ) {
00625           if( i == *order ) {
00626             found = TRUE;
00627           } else {
00628             i++;
00629             sigl = sigl->next;
00630           }
00631         } else {
00632           sigl = sigl->next;
00633         }
00634       }
00635 
00636       /*
00637        If we found our signal to bind to, do it now; otherwise, just skip ahead (the error will be handled by
00638        the calling function.
00639       */
00640       if( sigl != NULL ) {
00641 
00642         /* Create signal name to bind */
00643         unsigned int rv = snprintf( sig_name, 4096, "%s.%s", name, sigl->sig->name );
00644         assert( rv < 4096 );
00645 
00646         /* Add the signal to the binding list */
00647         bind_add( 0, sig_name, expr, funit_exp );
00648 
00649         /* Specify that this vector will be assigned by Covered and not the dumpfile */
00650         sigl->sig->suppl.part.assigned = 1;
00651 
00652         /* Increment the port order number */
00653         (*order)++;
00654 
00655       }
00656 
00657     }
00658 
00659   }
00660 
00661   PROFILE_END;
00662 
00663 }


Variable Documentation

unsigned int curr_db
 

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

db** db_list
 

Array of database pointers storing all currently loaded databases.

bool debug_mode
 

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

exp_bind* eb_head [static]
 

Pointer to the head of the signal/functional unit/expression binding list.

exp_bind* eb_tail [static]
 

Pointer to the tail of the signal/functional unit/expression binding list.

funit_link* funit_head
 

char user_msg[USER_MSG_LENGTH]
 

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


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