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

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


Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
7/10/2006

#include <string.h>
#include <stdio.h>
#include "binding.h"
#include "defines.h"
#include "expr.h"
#include "func_unit.h"
#include "gen_item.h"
#include "instance.h"
#include "link.h"
#include "obfuscate.h"
#include "param.h"
#include "scope.h"
#include "statement.h"
#include "util.h"
#include "vector.h"
#include "vsignal.h"

Functions

int parse_static_expr (char *str, func_unit *funit, int lineno, bool no_genvars)
void gen_item_stringify (gen_item *gi, char *str, unsigned int str_len)
void gen_item_display (gen_item *gi)
 Displays the specified generate item to standard output.

void gen_item_display_block_helper (gen_item *root)
void gen_item_display_block (gen_item *root)
 Displays an entire generate block.

bool gen_item_compare (gen_item *gi1, gen_item *gi2)
gen_itemgen_item_find (gen_item *root, gen_item *gi)
 Searches for a generate item in the generate block of root that matches gi.

void gen_item_remove_if_contains_expr_calling_stmt (gen_item *gi, statement *stmt)
 Searches for an expression in the generate list that calls the given statement.

void gen_item_get_genvar (char *varname, char **pre, char **genvar, char **post)
bool gen_item_varname_contains_genvar (char *name)
 Returns TRUE if the specified variable name contains a generate variable within it.

char * gen_item_calc_signal_name (const char *name, func_unit *funit, int line, bool no_genvars)
 Returns the actual signal name specified by the given signal name which references a generated hierarchy.

gen_itemgen_item_create_expr (expression *expr)
 Creates a generate item for an expression.

gen_itemgen_item_create_sig (vsignal *sig)
 Creates a generate item for a signal.

gen_itemgen_item_create_stmt (statement *stmt)
 Creates a generate item for a statement.

gen_itemgen_item_create_inst (funit_inst *inst)
 Creates a generate item for an instance.

gen_itemgen_item_create_tfn (funit_inst *inst)
 Creates a generate item for a namespace.

gen_itemgen_item_create_bind (const char *name, expression *expr)
 Creates a generate item for a binding.

void gen_item_resize_stmts_and_sigs (gen_item *gi, func_unit *funit)
 Resizes all statements and signals in the given generate item block.

void gen_item_assign_ids (gen_item *gi, func_unit *funit)
 Assigns unique signal ID or expression IDs to all expressions for specified statement block.

void gen_item_db_write (gen_item *gi, uint32 type, FILE *ofile)
 Outputs the current generate item to the given output file if it matches the type specified.

void gen_item_db_write_expr_tree (gen_item *gi, FILE *ofile)
 Outputs the entire expression tree from the given generate statement.

bool gen_item_connect (gen_item *gi1, gen_item *gi2, int conn_id, bool stop_on_null)
 Connects a generate item block to a new generate item.

void gen_item_resolve (gen_item *gi, funit_inst *inst)
void gen_item_bind (gen_item *gi)
 Checks generate item and if it is a bind, adds it to binding pool and returns TRUE.

void generate_resolve (funit_inst *root)
 Resolves all generate items in the design.

bool generate_remove_stmt_helper (funit_inst *root, statement *stmt)
bool generate_remove_stmt (statement *stmt)
 Removes the given generate statement from the correct instance.

void gen_item_dealloc (gen_item *gi, bool rm_elem)
 Deallocates all associated memory for the given generate item.


Variables

db ** db_list
unsigned int curr_db
char user_msg [USER_MSG_LENGTH]
bool debug_mode
func_unitcurr_funit
int curr_sig_id


Function Documentation

void gen_item_assign_ids gen_item gi,
func_unit funit
 

Assigns unique signal ID or expression IDs to all expressions for specified statement block.

Exceptions:
anonymous statement_assign_expr_ids
Assigns unique expression and signal IDs to each expression in the tree given for a generated statement or for the given signal.
Parameters:
gi  Pointer to generate item to check and assign expression IDs for
funit  Pointer to functional unit containing this generate item

00768   { PROFILE(GEN_ITEM_ASSIGN_IDS);
00769 
00770   if( gi->suppl.part.removed == 0 ) {
00771 
00772     /* Assign expression IDs if this is a statement */
00773     if( gi->suppl.part.type == GI_TYPE_STMT ) {
00774       statement_assign_expr_ids( gi->elem.stmt, funit );
00775     } else if( gi->suppl.part.type == GI_TYPE_SIG ) {
00776       gi->elem.sig->id = curr_sig_id;
00777       curr_sig_id++;
00778     }
00779 
00780   }
00781 
00782   PROFILE_END;
00783 
00784 }

void gen_item_bind gen_item gi  ) 
 

Checks generate item and if it is a bind, adds it to binding pool and returns TRUE.

Updates the specified expression name to be that of the generate item name if the current generate item is a BIND type.

Parameters:
gi  Pointer to generate item to examine

01048   { PROFILE(GEN_ITEM_BIND);
01049 
01050   if( gi->suppl.part.type == GI_TYPE_BIND ) {
01051 
01052     /* Remove the current name */
01053     free_safe( gi->elem.expr->name, (strlen( gi->elem.expr->name ) + 1) );
01054 
01055     /* Assign the new name */
01056     gi->elem.expr->name = strdup_safe( gi->varname );
01057 
01058   }
01059 
01060   PROFILE_END;
01061 
01062 }

char* gen_item_calc_signal_name const char *  name,
func_unit funit,
int  line,
bool  no_genvars
 

Returns the actual signal name specified by the given signal name which references a generated hierarchy.

Parameters:
name Name of signal that we possibly need to convert if it contains generate variable(s)
funit Pointer to current functional unit
line Line number in which the signal's expression exists
no_genvars If set to TRUE, we need to make sure that we do not see a generate variable in the generate hierarchical expression.
Returns:
Returns allocated string containing the signal name with embedded generate variables evaluated
Exceptions:
anonymous parse_static_expr Throw
Iterates through the given name, substituting any found generate variables with their current value.

00445   { PROFILE(GEN_ITEM_CALC_SIGNAL_NAME);
00446 
00447   char* new_name = NULL;  /* Return value of this function */
00448   char* tmpname;          /* Temporary name of current part of variable */
00449   char* pre;              /* String prior to the generate variable */
00450   char* genvar;           /* Generate variable */
00451   char* post;             /* String after the generate variable */
00452   char  intstr[20];       /* String containing an integer value */
00453   char* ptr;              /* Pointer to allocated memory for name */
00454 
00455   /* Allocate memory */
00456   tmpname  = strdup_safe( name );
00457   ptr      = tmpname;
00458   new_name = strdup_safe( "" );
00459 
00460   Try {
00461 
00462     do {
00463       gen_item_get_genvar( tmpname, &pre, &genvar, &post );
00464       if( genvar != NULL ) {
00465         unsigned int rv = snprintf( intstr, 20, "%d", parse_static_expr( genvar, funit, line, no_genvars ) );
00466         assert( rv < 20 );
00467         new_name = (char*)realloc_safe( new_name, (strlen( new_name ) + 1), (strlen( new_name ) + strlen( pre ) + strlen( intstr ) + 3) );
00468         strncat( new_name, pre, strlen( pre ) );
00469         strncat( new_name, "[", 1 );
00470         strncat( new_name, intstr, strlen( intstr ) );
00471         strncat( new_name, "]", 1 );
00472         tmpname = post;
00473       } else {
00474         new_name = (char*)realloc_safe( new_name, (strlen( new_name ) + 1), (strlen( new_name ) + strlen( pre ) + 1) );
00475         strncat( new_name, pre, strlen( pre ) );
00476       }
00477     } while( genvar != NULL );
00478 
00479   } Catch_anonymous {
00480     free_safe( new_name, (strlen( new_name ) + 1) );
00481     free_safe( ptr, (strlen( name ) + 1) );
00482     Throw 0;
00483   }
00484 
00485   /* Deallocate memory */
00486   free_safe( ptr, (strlen( name ) + 1) );
00487 
00488   /* Make sure that the new_name is set to something */
00489   assert( new_name != NULL );
00490 
00491   return( new_name );
00492 
00493 }

bool gen_item_compare gen_item gi1,
gen_item gi2
[static]
 

Returns:
Returns TRUE if the two specified generate items are equivalent; otherwise, returns FALSE.
Parameters:
gi1  Pointer to first generate item to compare
gi2  Pointer to second generate item to compare

00204   { PROFILE(GEN_ITEM_COMPARE);
00205 
00206   bool retval = FALSE;  /* Return value for this function */
00207 
00208   if( (gi1 != NULL) && (gi2 != NULL) && (gi1->suppl.part.type == gi2->suppl.part.type) ) {
00209 
00210     switch( gi1->suppl.part.type ) {
00211       case GI_TYPE_EXPR :  retval = (gi1->elem.expr->id == gi2->elem.expr->id) ? TRUE : FALSE;  break;
00212       case GI_TYPE_SIG  :  retval = scope_compare( gi1->elem.sig->name, gi2->elem.sig->name );  break;
00213       case GI_TYPE_STMT :  retval = (gi1->elem.stmt->exp->id == gi2->elem.stmt->exp->id) ? TRUE : FALSE;  break;
00214       case GI_TYPE_INST :
00215       case GI_TYPE_TFN  :  retval = (strcmp( gi1->elem.inst->name, gi2->elem.inst->name ) == 0) ? TRUE : FALSE;  break;
00216       case GI_TYPE_BIND :  retval = ((gi1->elem.expr->id == gi2->elem.expr->id) &&
00217                                      (strcmp( gi1->varname, gi2->varname ) == 0)) ? TRUE : FALSE;  break;
00218       default           :  break;
00219     }
00220 
00221   }
00222 
00223   PROFILE_END;
00224 
00225   return( retval );
00226 
00227 }

bool gen_item_connect gen_item gi1,
gen_item gi2,
int  conn_id,
bool  stop_on_null
 

Connects a generate item block to a new generate item.

Returns:
Returns TRUE if the connection was successful; otherwise, returns FALSE.
Parameters:
gi1  Pointer to generate item block to connect to gi2
gi2  Pointer to generate item to connect to gi1
conn_id  Connection ID
stop_on_null  Sets stop bit(s) if a NULL next_true/next_false pointer is found

00845   { PROFILE(GEN_ITEM_CONNECT);
00846 
00847   bool retval = FALSE;  /* Return value for this function */
00848 
00849   /* Set the connection ID */
00850   gi1->suppl.part.conn_id = conn_id;
00851 
00852   /* If both paths go to the same destination, only parse one path */
00853   if( gi1->next_true == gi1->next_false ) {
00854 
00855     /* If the TRUE path is NULL, connect it to the new statement */
00856     if( gi1->next_true == NULL ) {
00857       gi1->next_true  = gi2;
00858       gi1->next_false = gi2;
00859       if( (gi1->next_true->suppl.part.conn_id == conn_id) || stop_on_null ) {
00860         gi1->suppl.part.stop_true  = 1;
00861         gi1->suppl.part.stop_false = 1;
00862       }
00863       retval = TRUE;
00864     } else if( gi1->next_true->suppl.part.conn_id == conn_id ) {
00865       gi1->suppl.part.stop_true  = 1;
00866       gi1->suppl.part.stop_false = 1;
00867 
00868     /* If the TRUE path leads to a loop/merge, stop traversing */
00869     } else if( gi1->next_true != gi2 ) {
00870       retval |= gen_item_connect( gi1->next_true, gi2, conn_id, stop_on_null );
00871     }
00872 
00873   } else {
00874 
00875     /* Traverse FALSE path */
00876     if( gi1->next_false == NULL ) {
00877       gi1->next_false = gi2;
00878       if( (gi1->next_false->suppl.part.conn_id == conn_id) || stop_on_null ) {
00879         gi1->suppl.part.stop_false = 1;
00880       } else {
00881         gi1->next_false->suppl.part.conn_id = conn_id;
00882       }
00883       retval = TRUE;
00884     } else if( gi1->next_false->suppl.part.conn_id == conn_id ) {
00885       gi1->suppl.part.stop_false = 1;
00886     } else if( gi1->next_false != gi2 ) {
00887       retval |= gen_item_connect( gi1->next_false, gi2, conn_id, stop_on_null );
00888     }
00889 
00890     /* Traverse TRUE path */
00891     if( gi1->next_true == NULL ) {
00892       gi1->next_true = gi2;
00893       if( (gi1->next_true->suppl.part.conn_id == conn_id) || stop_on_null ) {
00894         gi1->suppl.part.stop_true = 1;
00895       }
00896       retval = TRUE;
00897     } else if( gi1->next_true->suppl.part.conn_id == conn_id ) {
00898       gi1->suppl.part.stop_true = 1;
00899     } else if( (gi1->next_true != gi2) && (gi1->suppl.part.type != GI_TYPE_TFN) && (gi1->varname == NULL) ) {
00900       retval |= gen_item_connect( gi1->next_true, gi2, conn_id, TRUE );
00901     }
00902 
00903   }
00904 
00905   PROFILE_END;
00906 
00907   return( retval );
00908 
00909 }

gen_item* gen_item_create_bind const char *  name,
expression expr
 

Creates a generate item for a binding.

Parameters:
name Name of signal to bind to
expr Pointer to expression to bind signal to
Returns:
Returns a pointer to create generate item.
Create a new generate item for a namespace.

00691   { PROFILE(GEN_ITEM_CREATE_BIND);
00692 
00693   gen_item* gi;
00694 
00695   /* Create the generate item for a namespace */
00696   gi = (gen_item*)malloc_safe( sizeof( gen_item ) );
00697   gi->elem.expr       = expr;
00698   gi->suppl.all       = 0;
00699   gi->suppl.part.type = GI_TYPE_BIND;
00700   gi->varname         = strdup_safe( name );
00701   gi->next_true       = NULL;
00702   gi->next_false      = NULL;
00703 
00704 #ifdef DEBUG_MODE
00705   if( debug_mode ) {
00706     char         str[USER_MSG_LENGTH];
00707     unsigned int rv;
00708     gen_item_stringify( gi, str, USER_MSG_LENGTH );
00709     rv = snprintf( user_msg, USER_MSG_LENGTH, "In gen_item_create_bind, %s", str );
00710     assert( rv < USER_MSG_LENGTH );
00711     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00712   }
00713 #endif
00714 
00715   return( gi );
00716 
00717 }

gen_item* gen_item_create_expr expression expr  ) 
 

Creates a generate item for an expression.

Parameters:
expr Pointer to root expression to create (this is an expression from a FOR, IF or CASE statement)
Returns:
Returns a pointer to created generate item.
Creates a new generate item for an expression.

00504   { PROFILE(GEN_ITEM_CREATE_EXPR);
00505 
00506   gen_item* gi;
00507 
00508   /* Create the generate item for an expression */
00509   gi = (gen_item*)malloc_safe( sizeof( gen_item ) );
00510   gi->elem.expr       = expr;
00511   gi->suppl.all       = 0;
00512   gi->suppl.part.type = GI_TYPE_EXPR;
00513   gi->varname         = NULL;
00514   gi->next_true       = NULL;
00515   gi->next_false      = NULL;
00516 
00517 #ifdef DEBUG_MODE
00518   if( debug_mode ) {
00519     char         str[USER_MSG_LENGTH];
00520     unsigned int rv;
00521     gen_item_stringify( gi, str, USER_MSG_LENGTH );
00522     rv = snprintf( user_msg, USER_MSG_LENGTH, "In gen_item_create_expr, %s", str );
00523     assert( rv < USER_MSG_LENGTH );
00524     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00525   }
00526 #endif
00527 
00528   return( gi );
00529 
00530 }

gen_item* gen_item_create_inst funit_inst inst  ) 
 

Creates a generate item for an instance.

Parameters:
inst Pointer to instance to create a generate item for (instantiations)
Returns:
Returns a pointer to create generate item.
Create a new generate item for an instance.

00615   { PROFILE(GEN_ITEM_CREATE_INST);
00616 
00617   gen_item* gi;
00618 
00619   /* Create the generate item for an instance */
00620   gi = (gen_item*)malloc_safe( sizeof( gen_item ) );
00621   gi->elem.inst       = inst;
00622   gi->suppl.all       = 0;
00623   gi->suppl.part.type = GI_TYPE_INST;
00624   gi->varname         = NULL;
00625   gi->next_true       = NULL;
00626   gi->next_false      = NULL;
00627 
00628 #ifdef DEBUG_MODE
00629   if( debug_mode ) {
00630     char         str[USER_MSG_LENGTH];
00631     unsigned int rv;
00632     gen_item_stringify( gi, str, USER_MSG_LENGTH );
00633     rv = snprintf( user_msg, USER_MSG_LENGTH, "In gen_item_create_inst, %s", str );
00634     assert( rv < USER_MSG_LENGTH );
00635     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00636   }
00637 #endif
00638 
00639   return( gi );
00640 
00641 }

gen_item* gen_item_create_sig vsignal sig  ) 
 

Creates a generate item for a signal.

Parameters:
sig Pointer to signal to create a generate item for (wire/reg instantions)
Returns:
Returns a pointer to created generate item.
Creates a new generate item for a signal.

00541   { PROFILE(GEN_ITEM_CREATE_SIG);
00542 
00543   gen_item* gi;
00544 
00545   /* Create the generate item for a signal */
00546   gi = (gen_item*)malloc_safe( sizeof( gen_item ) );
00547   gi->elem.sig        = sig;
00548   gi->suppl.all       = 0;
00549   gi->suppl.part.type = GI_TYPE_SIG;
00550   gi->varname         = NULL;
00551   gi->next_true       = NULL;
00552   gi->next_false      = NULL;
00553 
00554 #ifdef DEBUG_MODE
00555   if( debug_mode ) {
00556     char         str[USER_MSG_LENGTH];
00557     unsigned int rv;
00558     gen_item_stringify( gi, str, USER_MSG_LENGTH );
00559     rv = snprintf( user_msg, USER_MSG_LENGTH, "In gen_item_create_sig, %s", str );
00560     assert( rv < USER_MSG_LENGTH );
00561     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00562   }
00563 #endif
00564 
00565   return( gi );
00566 
00567 }

gen_item* gen_item_create_stmt statement stmt  ) 
 

Creates a generate item for a statement.

Parameters:
stmt Pointer to statement to create a generate item for (assign, always, initial blocks)
Returns:
Returns a pointer to create generate item.
Create a new generate item for a statement.

00578   { PROFILE(GEN_ITEM_CREATE_STMT);
00579 
00580   gen_item* gi;
00581 
00582   /* Create the generate item for a statement */
00583   gi = (gen_item*)malloc_safe( sizeof( gen_item ) );
00584   gi->elem.stmt       = stmt;
00585   gi->suppl.all       = 0;
00586   gi->suppl.part.type = GI_TYPE_STMT;
00587   gi->varname         = NULL;
00588   gi->next_true       = NULL;
00589   gi->next_false      = NULL;
00590 
00591 #ifdef DEBUG_MODE
00592   if( debug_mode ) {
00593     char         str[USER_MSG_LENGTH];
00594     unsigned int rv;
00595     gen_item_stringify( gi, str, USER_MSG_LENGTH );
00596     rv = snprintf( user_msg, USER_MSG_LENGTH, "In gen_item_create_stmt, %s", str );
00597     assert( rv < USER_MSG_LENGTH );
00598     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00599   }
00600 #endif
00601 
00602   return( gi );
00603 
00604 }

gen_item* gen_item_create_tfn funit_inst inst  ) 
 

Creates a generate item for a namespace.

Parameters:
inst Pointer to namespace to create a generate item for (named blocks, functions or tasks)
Returns:
Returns a pointer to create generate item.
Create a new generate item for a namespace.

00652   { PROFILE(GEN_ITEM_CREATE_TFN);
00653 
00654   gen_item* gi;
00655 
00656   /* Create the generate item for a namespace */
00657   gi = (gen_item*)malloc_safe( sizeof( gen_item ) );
00658   gi->elem.inst       = inst;
00659   gi->suppl.all       = 0;
00660   gi->suppl.part.type = GI_TYPE_TFN;
00661   gi->varname         = NULL;
00662   gi->next_true       = NULL;
00663   gi->next_false      = NULL;
00664 
00665 #ifdef DEBUG_MODE
00666   if( debug_mode ) {
00667     char str[USER_MSG_LENGTH];
00668     unsigned int rv;
00669     gen_item_stringify( gi, str, USER_MSG_LENGTH );
00670     rv = snprintf( user_msg, USER_MSG_LENGTH, "In gen_item_create_tfn, %s", str );
00671     assert( rv < USER_MSG_LENGTH );
00672     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00673   }
00674 #endif
00675 
00676   return( gi );
00677 
00678 }

void gen_item_db_write gen_item gi,
uint32  type,
FILE *  ofile
 

Outputs the current generate item to the given output file if it matches the type specified.

Checks the given generate item against the supplied type. If they match, outputs the given generate item to the specified output file. If they do not match, nothing is done.

Parameters:
gi  Pointer to current generate item to test and output
type  Specifies the type of the generate item to output
ofile  Output file to display generate item to

00795   { PROFILE(GEN_ITEM_DB_WRITE);
00796 
00797   /* If the types match, output based on type */
00798   if( (gi->suppl.part.type == type) && (gi->suppl.part.removed == 0) ) {
00799 
00800     switch( type ) {
00801       case GI_TYPE_SIG :
00802         vsignal_db_write( gi->elem.sig, ofile );
00803         break;
00804       case GI_TYPE_STMT :
00805         statement_db_write_tree( gi->elem.stmt, ofile );
00806         break;
00807       default :  /* Should never be called */
00808         assert( (type == GI_TYPE_SIG) || (type == GI_TYPE_STMT) );
00809         break;
00810     }
00811 
00812   }
00813 
00814   PROFILE_END;
00815 
00816 }

void gen_item_db_write_expr_tree gen_item gi,
FILE *  ofile
 

Outputs the entire expression tree from the given generate statement.

Outputs all expressions for the statement contained in the specified generate item.

Parameters:
gi  Pointer to current generate item to test and output
ofile  Output file to display generate item to

00824   { PROFILE(GEN_ITEM_DB_WRITE_EXPR_TREE);
00825 
00826   /* Only do this for statements */
00827   if( (gi->suppl.part.type == GI_TYPE_STMT) && (gi->suppl.part.removed == 0) ) {
00828 
00829     statement_db_write_expr_tree( gi->elem.stmt, ofile );
00830 
00831   }
00832 
00833   PROFILE_END;
00834 
00835 }

void gen_item_dealloc gen_item gi,
bool  rm_elem
 

Deallocates all associated memory for the given generate item.

Recursively deallocates the gen_item structure tree.

Parameters:
gi  Pointer to gen_item structure to deallocate
rm_elem  If set to TRUE, removes the associated element

01168   { PROFILE(GEN_ITEM_DEALLOC);
01169 
01170   if( gi != NULL ) {
01171 
01172     /* Deallocate children first */
01173     if( gi->next_true == gi->next_false ) {
01174       if( gi->suppl.part.stop_true == 0 ) {
01175         gen_item_dealloc( gi->next_true, rm_elem );
01176       }
01177     } else {
01178       if( gi->suppl.part.stop_false == 0 ) {
01179         gen_item_dealloc( gi->next_false, rm_elem );
01180       }
01181       if( gi->suppl.part.stop_true == 0 ) {
01182         gen_item_dealloc( gi->next_true, rm_elem );
01183       }
01184     }
01185 
01186     /* If we need to remove the current element, do so now */
01187     if( rm_elem ) {
01188       switch( gi->suppl.part.type ) {
01189         case GI_TYPE_EXPR :
01190           expression_dealloc( gi->elem.expr, FALSE );
01191           break;
01192         case GI_TYPE_SIG  :
01193           vsignal_dealloc( gi->elem.sig );
01194           break;
01195         case GI_TYPE_STMT :
01196           statement_dealloc_recursive( gi->elem.stmt, FALSE );
01197           break;
01198         case GI_TYPE_INST :
01199         case GI_TYPE_TFN  :
01200           instance_dealloc_tree( gi->elem.inst );
01201           break;
01202         case GI_TYPE_BIND :
01203           break;
01204         default           :  break;
01205       }
01206     }
01207 
01208     /* Remove the varname if necessary */
01209     free_safe( gi->varname, (strlen( gi->varname ) + 1) );
01210 
01211     /* Now deallocate ourselves */
01212     free_safe( gi, sizeof( gen_item ) );
01213 
01214   }
01215 
01216   PROFILE_END;
01217 
01218 } 

void gen_item_display gen_item gi  ) 
 

Displays the specified generate item to standard output.

Displays the contents of the specified generate item to standard output (used for debugging purposes).

Parameters:
gi  Pointer to generate item to display

00134   { PROFILE(GEN_ITEM_DISPLAY);
00135 
00136   char str[4096];  /* String to store data into */
00137 
00138   gen_item_stringify( gi, str, 4096 );
00139 
00140   printf( "  %s\n", str );
00141 
00142   PROFILE_END;
00143 
00144 }

void gen_item_display_block gen_item root  ) 
 

Displays an entire generate block.

Displays an entire generate block to standard output (used for debugging purposes).

Parameters:
root  Pointer to starting generate item to display

00187   { PROFILE(GEN_ITEM_DISPLAY_BLOCK);
00188 
00189   printf( "Generate block:\n" );
00190 
00191   gen_item_display_block_helper( root );
00192 
00193   PROFILE_END;
00194 
00195 }

void gen_item_display_block_helper gen_item root  )  [static]
 

Displays an entire generate block to standard output (used for debugging purposes).

Parameters:
root  Pointer to starting generate item to display

00151   { PROFILE(GEN_ITEM_DISPLAY_BLOCK_HELPER);
00152 
00153   if( root != NULL ) {
00154 
00155     /* Display ourselves */
00156     gen_item_display( root );
00157 
00158     if( root->next_true == root->next_false ) {
00159 
00160       if( root->suppl.part.stop_true == 0 ) {
00161         gen_item_display_block_helper( root->next_true );
00162       }
00163 
00164     } else {
00165 
00166       if( root->suppl.part.stop_true == 0 ) {
00167         gen_item_display_block_helper( root->next_true );
00168       }
00169 
00170       if( root->suppl.part.stop_false == 0 ) {
00171         gen_item_display_block_helper( root->next_false );
00172       }
00173 
00174     }
00175 
00176   }
00177 
00178   PROFILE_END;
00179 
00180 }

gen_item* gen_item_find gen_item root,
gen_item gi
 

Searches for a generate item in the generate block of root that matches gi.

Returns:
Returns a pointer to the generate item that matches the given generate item in the given generate item block. Returns NULL if it was not able to find a matching item.
Recursively traverses the specified generate item block searching for a generate item that matches the specified generate item.
Parameters:
root  Pointer to root of generate item block to search in
gi  Pointer to generate item to search for

00240   { PROFILE(GEN_ITEM_FIND);
00241 
00242   gen_item* found = NULL;  /* Return value for this function */
00243 
00244   assert( gi != NULL );
00245 
00246   if( root != NULL ) {
00247 
00248     if( gen_item_compare( root, gi ) ) {
00249 
00250       found = root;
00251 
00252     } else {
00253 
00254       /* If both true and false paths lead to same item, just traverse the true path */
00255       if( root->next_true == root->next_false ) {
00256 
00257         if( root->suppl.part.stop_true == 0 ) {
00258           found = gen_item_find( root->next_true, gi );
00259         }
00260 
00261       /* Otherwise, traverse both true and false paths */
00262       } else if( (root->suppl.part.stop_true == 0) && ((found = gen_item_find( root->next_true, gi )) == NULL) ) {
00263 
00264         if( root->suppl.part.stop_false == 0 ) {
00265           found = gen_item_find( root->next_false, gi );
00266         }
00267 
00268       }
00269 
00270     }
00271 
00272   }
00273 
00274   PROFILE_END;
00275 
00276   return( found );
00277 
00278 }

void gen_item_get_genvar char *  varname,
char **  pre,
char **  genvar,
char **  post
[static]
 

Searches the given variable name for a generate variable. If one is found, pre is set to point to the string preceding the generate variable, genvar is set to point to the beginning of the generate variable, and post is set to point to the string succeeding the ']'.

Parameters:
varname  Variable name to search
pre  Reference pointer to string preceding the generate variable
genvar  Reference pointer to found generate variable name
post  Reference pointer to string succeeding the generate variable

00337   { PROFILE(GEN_ITEM_GET_GENVAR);
00338 
00339   int i = 0;  /* Loop iterator */
00340 
00341   /* Initialize pointers */
00342   *pre    = varname;
00343   *genvar = NULL;
00344   *post   = NULL;
00345 
00346   /* Iterate through the variable name until we either reach the end of the string or until we have found a genvar */
00347   while( (varname[i] != '\0') && (*genvar == NULL) ) {
00348 
00349     /* Iterate through the varname until we see either a \, [ or terminating character */
00350     while( (varname[i] != '\\') && (varname[i] != '[') && (varname[i] != '\0') ) {
00351       i++;
00352     }
00353  
00354     /* If we saw a \ character, keep going until we see whitespace */
00355     if( varname[i] == '\\' ) {
00356       while( (varname[i] != ' ') && (varname[i] != '\n') && (varname[i] != '\t') && (varname[i] != '\r') ) {
00357         i++;
00358       }
00359 
00360     /* If we saw a [, get the genvar name, stripping all whitespace from the name */
00361     } else if( varname[i] == '[' ) {
00362 
00363       varname[i] = '\0';
00364       i++;
00365       while( (varname[i] == ' ') || (varname[i] == '\n') || (varname[i] == '\t') || (varname[i] == '\r') ) {
00366         i++;
00367       }
00368       *genvar = (varname + i);
00369       while( (varname[i] != ' ') && (varname[i] != '\n') && (varname[i] != '\t') && (varname[i] != '\r') && (varname[i] != ']') ) {
00370         i++;
00371       }
00372       if( varname[i] != ']' ) {
00373         varname[i] = '\0';
00374         i++;
00375         while( varname[i] != ']' ) {
00376           i++;
00377         }
00378       } else {
00379         varname[i] = '\0';
00380       }
00381       i++;
00382       *post = (varname + i);
00383 
00384     }
00385 
00386   }
00387 
00388   PROFILE_END;
00389 
00390 }

void gen_item_remove_if_contains_expr_calling_stmt gen_item gi,
statement stmt
 

Searches for an expression in the generate list that calls the given statement.

Removes the given generate item if it contains an expressions that calls a statement.

Parameters:
gi  Pointer to generate item list to search
stmt  Pointer to statement to search for

00286   { PROFILE(GEN_ITEM_REMOVE_IF_CONTAINS_EXPR_CALLING_STMT);
00287 
00288   if( gi != NULL ) {
00289 
00290     if( gi->suppl.part.type == GI_TYPE_STMT ) {
00291 
00292       if( statement_contains_expr_calling_stmt( gi->elem.stmt, stmt ) ) {
00293         gi->suppl.part.removed = 1;
00294       }
00295 
00296     } else {
00297 
00298       /* If both true and false paths lead to same item, just traverse the true path */
00299       if( gi->next_true == gi->next_false ) {
00300 
00301         if( gi->suppl.part.stop_true == 0 ) {
00302           gen_item_remove_if_contains_expr_calling_stmt( gi->next_true, stmt );
00303         }
00304 
00305       /* Otherwise, traverse both true and false paths */
00306       } else {
00307 
00308         if( gi->suppl.part.stop_true == 0 ) {
00309           gen_item_remove_if_contains_expr_calling_stmt( gi->next_true, stmt );
00310         }
00311 
00312         if( gi->suppl.part.stop_false == 0 ) {
00313           gen_item_remove_if_contains_expr_calling_stmt( gi->next_false, stmt );
00314         }
00315 
00316       }
00317 
00318     }
00319 
00320   }
00321 
00322   PROFILE_END;
00323 
00324 }

void gen_item_resize_stmts_and_sigs gen_item gi,
func_unit funit
 

Resizes all statements and signals in the given generate item block.

Exceptions:
anonymous vsignal_create_vec statement_size_elements gen_item_resize_stmts_and_sigs gen_item_resize_stmts_and_sigs gen_item_resize_stmts_and_sigs
Recursively iterates the the specified generate item block, resizing all statements within that block.
Parameters:
gi  Pointer to generate item block to check
funit  Pointer to functional unit that contains this generate item

00728   { PROFILE(GEN_ITEM_RESIZE_STMTS_AND_SIGS);
00729 
00730   if( gi != NULL ) {
00731 
00732     /* Resize our statement, if we are one */
00733     if( gi->suppl.part.type == GI_TYPE_STMT ) {
00734       statement_size_elements( gi->elem.stmt, funit );
00735     } else if( gi->suppl.part.type == GI_TYPE_SIG ) {
00736       vsignal_create_vec( gi->elem.sig );
00737     }
00738 
00739     /* Go to the next generate item */
00740     if( gi->next_true == gi->next_false ) {
00741       if( gi->suppl.part.stop_true == 0 ) {
00742         gen_item_resize_stmts_and_sigs( gi->next_true, funit );
00743       }
00744     } else {
00745       if( gi->suppl.part.stop_false == 0 ) {
00746         gen_item_resize_stmts_and_sigs( gi->next_false, funit );
00747       }
00748       if( gi->suppl.part.stop_true == 0 ) {
00749         gen_item_resize_stmts_and_sigs( gi->next_true, funit );
00750       }
00751     }
00752 
00753   }
00754 
00755   PROFILE_END;
00756 
00757 }

void gen_item_resolve gen_item gi,
funit_inst inst
[static]
 

Exceptions:
anonymous gen_item_calc_signal_name Throw expression_resize expression_operate_recursively gen_item_resolve gen_item_resolve gen_item_resolve gen_item_resolve gen_item_resolve gen_item_resolve gen_item_resolve gen_item_resolve
Recursively iterates through the entire generate block specified by gi, resolving all generate items within it. This is called by the generate_resolve function (in the middle of the binding process) and by the funit_size_elements function (just prior to outputting this instance to the CDD file).
Parameters:
gi  Pointer to current generate item to resolve
inst  Pointer to instance to store results to

00922   { PROFILE(GEN_ITEM_RESOLVE);
00923 
00924   funit_inst* child;    /* Pointer to child instance of this instance to resolve */
00925   char*       varname;  /* Pointer to new, substituted name (used for BIND types) */
00926 
00927   if( (gi != NULL) && (inst != NULL) ) {
00928 
00929 #ifdef DEBUG_MODE 
00930     if( debug_mode ) {
00931       char         str[USER_MSG_LENGTH];
00932       unsigned int rv;
00933       gen_item_stringify( gi, str, USER_MSG_LENGTH );
00934       rv = snprintf( user_msg, USER_MSG_LENGTH, "Resolving generate item, %s for inst: %s", str, obf_inst( inst->name ) );
00935       assert( rv < USER_MSG_LENGTH );
00936       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00937     }
00938 #endif
00939 
00940     /* Specify that this generate item has been resolved */
00941     gi->suppl.part.resolved = 1;
00942 
00943     switch( gi->suppl.part.type ) {
00944   
00945       case GI_TYPE_EXPR :
00946         /* Recursively resize the expression tree if we have not already done this */
00947         if( gi->elem.expr->exec_num == 0 ) {
00948           expression_resize( gi->elem.expr, inst->funit, TRUE, FALSE );
00949         }
00950         expression_operate_recursively( gi->elem.expr, inst->funit, FALSE );
00951         if( ESUPPL_IS_TRUE( gi->elem.expr->suppl ) ) {
00952           gen_item_resolve( gi->next_true, inst );
00953         } else {
00954           gen_item_resolve( gi->next_false, inst );
00955         }
00956         break;
00957 
00958       case GI_TYPE_SIG :
00959         gitem_link_add( gen_item_create_sig( gi->elem.sig ), &(inst->gitem_head), &(inst->gitem_tail) );
00960         gen_item_resolve( gi->next_true, inst );
00961         break;
00962 
00963       case GI_TYPE_STMT :
00964         gitem_link_add( gen_item_create_stmt( gi->elem.stmt ), &(inst->gitem_head), &(inst->gitem_tail) );
00965         gen_item_resolve( gi->next_true, inst );
00966         break;
00967 
00968       case GI_TYPE_INST :
00969         {
00970           funit_inst* tinst;
00971           if( (tinst = instance_copy( gi->elem.inst, inst, gi->elem.inst->name, gi->elem.inst->range, FALSE )) != NULL ) {
00972             param_resolve( tinst );
00973           }
00974           gen_item_resolve( gi->next_true, inst );
00975         }
00976         break;
00977 
00978       case GI_TYPE_TFN :
00979         if( gi->varname != NULL ) {
00980           char         inst_name[4096];
00981           vsignal*     genvar;
00982           func_unit*   found_funit;
00983           unsigned int rv;
00984           if( !scope_find_signal( gi->varname, inst->funit, &genvar, &found_funit, 0 ) ) {
00985             rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to find variable %s in module %s",
00986                            obf_sig( gi->varname ), obf_funit( inst->funit->name ) );
00987             assert( rv < USER_MSG_LENGTH );
00988             print_output( user_msg, FATAL, __FILE__, __LINE__ );
00989             Throw 0;
00990           }
00991           rv = snprintf( inst_name, 4096, "%s[%d]", gi->elem.inst->name, vector_to_int( genvar->value ) );
00992           assert( rv < 4096 );
00993           (void)instance_parse_add( &inst, inst->funit, gi->elem.inst->funit, inst_name, NULL, FALSE, TRUE, FALSE, TRUE );
00994           rv = snprintf( inst_name, 4096, "%s.%s[%d]", inst->name, gi->elem.inst->name, vector_to_int( genvar->value ) );
00995           assert( rv < 4096 );
00996           if( (child = instance_find_scope( inst, inst_name, TRUE )) != NULL ) {
00997             inst_parm_add_genvar( genvar, child );
00998           }
00999         } else {
01000           char         inst_name[4096];
01001           unsigned int rv;
01002           (void)instance_parse_add( &inst, inst->funit, gi->elem.inst->funit, gi->elem.inst->name, NULL, FALSE, TRUE, FALSE, TRUE );
01003           rv = snprintf( inst_name, 4096, "%s.%s", inst->name, gi->elem.inst->name );
01004           assert( rv < 4096 );
01005           child = instance_find_scope( inst, inst_name, TRUE );
01006         }
01007         if( child != NULL ) {
01008           param_resolve( child );
01009         }
01010         gen_item_resolve( gi->next_true, child );
01011         gen_item_resolve( gi->next_false, inst );
01012         break;
01013 
01014       case GI_TYPE_BIND :
01015         varname = gen_item_calc_signal_name( gi->varname, inst->funit, gi->elem.expr->line, FALSE );
01016         switch( gi->elem.expr->op ) {
01017           case EXP_OP_FUNC_CALL :  bind_add( FUNIT_FUNCTION,    varname, gi->elem.expr, inst->funit );  break;
01018           case EXP_OP_TASK_CALL :  bind_add( FUNIT_TASK,        varname, gi->elem.expr, inst->funit );  break;
01019           case EXP_OP_NB_CALL   :  bind_add( FUNIT_NAMED_BLOCK, varname, gi->elem.expr, inst->funit );  break;
01020           case EXP_OP_DISABLE   :  bind_add( 1,                 varname, gi->elem.expr, inst->funit );  break;
01021           default               :  bind_add( 0,                 varname, gi->elem.expr, inst->funit );  break;
01022         }
01023         gitem_link_add( gen_item_create_bind( varname, gi->elem.expr ), &(inst->gitem_head), &(inst->gitem_tail) );
01024         free_safe( varname, (strlen( varname ) + 1) ); 
01025         gen_item_resolve( gi->next_true, inst );
01026         break;
01027 
01028       default :
01029         assert( (gi->suppl.part.type == GI_TYPE_EXPR) || (gi->suppl.part.type == GI_TYPE_SIG) ||
01030                 (gi->suppl.part.type == GI_TYPE_STMT) || (gi->suppl.part.type == GI_TYPE_INST) ||
01031                 (gi->suppl.part.type == GI_TYPE_TFN)  || (gi->suppl.part.type == GI_TYPE_BIND) );
01032         break;
01033 
01034     }
01035 
01036   }
01037 
01038   PROFILE_END;
01039 
01040 }

void gen_item_stringify gen_item gi,
char *  str,
unsigned int  str_len
[static]
 

Creates a user-readable version of the specified generate item and stores it in the specified string.

Parameters:
gi  Pointer to generate item to stringify
str  Pointer to string to store data into
str_len  Number of available characters in the str string

00059   { PROFILE(GEN_ITEM_STRINGIFY);
00060 
00061   char* tmp;  /* Temporary string */
00062 
00063   assert( str_len > 0 );
00064 
00065   if( gi != NULL ) {
00066 
00067     unsigned int rv;
00068 
00069     /* Allocate some memory in the tmp string */
00070     tmp = (char*)malloc_safe_nolimit( str_len );
00071 
00072     rv = snprintf( str, str_len, "%p, suppl: %x", gi, gi->suppl.all );
00073     assert( rv < str_len );
00074 
00075     switch( gi->suppl.part.type ) {
00076       case GI_TYPE_EXPR :
00077         rv = snprintf( tmp, str_len, ", EXPR, %s", expression_string( gi->elem.expr ) );
00078         assert( rv < str_len );
00079         break;
00080       case GI_TYPE_SIG :
00081         rv = snprintf( tmp, str_len, ", SIG, name: %s", obf_sig( gi->elem.sig->name ) );
00082         assert( rv < str_len );
00083         break;
00084       case GI_TYPE_STMT :
00085         rv = snprintf( tmp, str_len, ", STMT, id: %d, line: %d", gi->elem.stmt->exp->id, gi->elem.stmt->exp->line );
00086         assert( rv < str_len );
00087         break;
00088       case GI_TYPE_INST :
00089         rv = snprintf( tmp, str_len, ", INST, name: %s", obf_inst( gi->elem.inst->name ) );
00090         assert( rv < str_len );
00091         break;
00092       case GI_TYPE_TFN :
00093         rv = snprintf( tmp, str_len, ", TFN, name: %s, type: %s", obf_inst( gi->elem.inst->name ), get_funit_type( gi->elem.inst->funit->type ) );
00094         assert( rv < str_len );
00095         break;
00096       case GI_TYPE_BIND :
00097         rv = snprintf( tmp, str_len, ", BIND, %s", expression_string( gi->elem.expr ) );
00098         assert( rv < str_len );
00099         break;
00100       default :
00101         strcpy( tmp, "UNKNOWN!\n" );
00102         break;
00103     }
00104     strcat( str, tmp );
00105 
00106     rv = snprintf( tmp, str_len, ", next_true: %p, next_false: %p", gi->next_true, gi->next_false );
00107     assert( rv < str_len );
00108     strcat( str, tmp );
00109 
00110     if( gi->varname != NULL ) {
00111       rv = snprintf( tmp, str_len, ", varname: %s", obf_sig( gi->varname ) );
00112       assert( rv < str_len );
00113       strcat( str, tmp );
00114     }
00115 
00116     /* Deallocate the temporary string memory */
00117     free_safe( tmp, str_len );
00118 
00119   } else {
00120 
00121     str[0] = '\0';
00122 
00123   }
00124 
00125   PROFILE_END;
00126 
00127 }

bool gen_item_varname_contains_genvar char *  name  ) 
 

Returns TRUE if the specified variable name contains a generate variable within it.

Parameters:
name Variable name to check
Returns:
Returns TRUE if the specified variable name contains a generate variable within it; otherwise, returns FALSE.
This function is called by db_create_expression() just before it places its signal name in the binding list. If the specified signal name contains a generate variable, we need to create a generate item binding element so that we can properly substitute the generate variable name with its current value.

00402                                                     { PROFILE(GEN_ITEM_VARNAME_CONTAINS_GENVAR);
00403 
00404   bool  retval = FALSE;  /* Return value for this function */
00405   char* pre;             /* String prior to the generate variable */
00406   char* genvar;          /* Generate variable */
00407   char* post;            /* String after the generate variable */
00408   char* tmpname;         /* Copy of the given name */
00409 
00410   /* Allocate memory */
00411   tmpname = strdup_safe( name );
00412   
00413   /* Find the first generate variable */
00414   gen_item_get_genvar( tmpname, &pre, &genvar, &post );
00415 
00416   if( genvar != NULL ) {
00417     retval = TRUE;
00418   }
00419 
00420   /* Deallocate memory */
00421   free_safe( tmpname, (strlen( name ) + 1)  );
00422 
00423   return( retval );
00424 
00425 }

bool generate_remove_stmt statement stmt  ) 
 

Removes the given generate statement from the correct instance.

Returns:
Returns TRUE if we found at least one match; otherwise, returns FALSE.
Iterates through the entire instance tree finding and "removing" all statement generate items that match the given statement ID. This will get called by the stmt_blk_remove() function when a statement has been found that does not exist in a functional unit.
Parameters:
stmt  Statement to set "remove" bit on

01144   { PROFILE(GENERATE_REMOVE_STMT);
01145 
01146   bool       retval = FALSE;  /* Return value for this function */
01147   inst_link* instl;           /* Pointer to current instance list to parse */
01148 
01149   /* Search for the generate item in the instance lists */
01150   instl = db_list[curr_db]->inst_head;
01151   while( instl != NULL ) {
01152     retval |= generate_remove_stmt_helper( instl->inst, stmt );
01153     instl = instl->next;
01154   }
01155 
01156   PROFILE_END;
01157 
01158   return( retval );
01159 
01160 }

bool generate_remove_stmt_helper funit_inst root,
statement stmt
[static]
 

Returns:
Returns TRUE if we found at least one match; otherwise, returns FALSE.
Parameters:
root  Pointer to root instance to traverse
stmt  Pointer to statement to find and remove

01106   { PROFILE(GENERATE_REMOVE_STMT_HELPER);
01107 
01108   bool        retval   = FALSE;  /* Return value for this function */
01109   funit_inst* curr_child;        /* Pointer to current child to search */
01110   gitem_link* gil;               /* Pointer to generate item link */
01111 
01112   /* Remove the generate item from the current instance if it exists there */
01113   gil = root->gitem_head;
01114   while( gil != NULL ) {
01115     if( (gil->gi->suppl.part.type == GI_TYPE_STMT) && (statement_find_statement( gil->gi->elem.stmt, stmt->exp->id ) != NULL) ) {
01116       gil->gi->suppl.part.removed = 1;
01117       retval = TRUE;
01118     }
01119     gil = gil->next;
01120   }
01121 
01122   /* Search child instances */
01123   curr_child = root->child_head;
01124   while( curr_child != NULL ) {
01125     retval |= generate_remove_stmt_helper( curr_child, stmt );
01126     curr_child = curr_child->next;
01127   }
01128 
01129   PROFILE_END;
01130 
01131   return( retval );
01132 
01133 }

void generate_resolve funit_inst root  ) 
 

Resolves all generate items in the design.

Exceptions:
anonymous generate_resolve gen_item_resolve
Recursively resolves all generate items in the design. This is called at a specific point in the binding process.
Parameters:
root  Pointer to current instance in instance tree to resolve for

01072   { PROFILE(GENERATE_RESOLVE);
01073 
01074   funit_inst* curr_child;  /* Pointer to current child to resolve for */
01075 
01076   if( root != NULL ) {
01077 
01078     /* Resolve ourself */
01079     if( root->funit != NULL ) {
01080       gitem_link* curr_gi = root->funit->gitem_head;
01081       while( curr_gi != NULL ) {
01082         gen_item_resolve( curr_gi->gi, root );
01083         curr_gi = curr_gi->next;
01084       }
01085     }
01086 
01087     /* Resolve children */
01088     curr_child = root->child_head;
01089     while( curr_child != NULL ) {
01090       generate_resolve( curr_child );
01091       curr_child = curr_child->next;
01092     } 
01093 
01094   }
01095 
01096   PROFILE_END;
01097 
01098 }

int parse_static_expr char *  str,
func_unit funit,
int  lineno,
bool  no_genvars
 


Variable Documentation

unsigned int curr_db
 

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

func_unit* curr_funit
 

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

int curr_sig_id
 

Signal ID that is used for identification purposes (each signal will receive a unique ID).

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.

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:22 2009 for Covered by doxygen 1.3.4