gen_item.c File Reference

#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)
static 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.
static void gen_item_display_block_helper (gen_item *root)
int gen_item_display_block (gen_item *root)
 Displays an entire generate block.
static 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.
static 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.
static 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_inst (funit_inst *inst)
 Resolves all generate items in the design.
static 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

Detailed Description

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

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

References curr_sig_id, gen_item_s::elem, GI_TYPE_SIG, GI_TYPE_STMT, vsignal_s::id, gen_item_s::part, PROFILE, PROFILE_END, gen_item_s::sig, statement_assign_expr_ids(), gen_item_s::stmt, and gen_item_s::suppl.

Referenced by instance_db_write().

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

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

References gen_item_s::elem, gen_item_s::expr, free_safe, GI_TYPE_BIND, expression_s::name, gen_item_s::part, PROFILE, PROFILE_END, strdup_safe, gen_item_s::suppl, and gen_item_s::varname.

Referenced by funit_size_elements().

01068   { PROFILE(GEN_ITEM_BIND);
01069 
01070   if( gi->suppl.part.type == GI_TYPE_BIND ) {
01071 
01072     /* Remove the current name */
01073     free_safe( gi->elem.expr->name, (strlen( gi->elem.expr->name ) + 1) );
01074 
01075     /* Assign the new name */
01076     gi->elem.expr->name = strdup_safe( gi->varname );
01077 
01078   }
01079 
01080   PROFILE_END;
01081 
01082 }

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.

References Catch_anonymous, free_safe, gen_item_get_genvar(), parse_static_expr(), PROFILE, realloc_safe, strdup_safe, Throw, and Try.

Referenced by gen_item_resolve().

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

static 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

References gen_item_s::elem, statement_s::exp, gen_item_s::expr, FALSE, GI_TYPE_BIND, GI_TYPE_EXPR, GI_TYPE_INST, GI_TYPE_SIG, GI_TYPE_STMT, GI_TYPE_TFN, expression_s::id, gen_item_s::inst, funit_inst_s::name, vsignal_s::name, gen_item_s::part, PROFILE, PROFILE_END, scope_compare(), gen_item_s::sig, gen_item_s::stmt, gen_item_s::suppl, TRUE, and gen_item_s::varname.

Referenced by gen_item_find().

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

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

References FALSE, gen_item_connect(), GI_TYPE_TFN, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, PROFILE, PROFILE_END, gen_item_s::suppl, TRUE, and gen_item_s::varname.

Referenced by db_gen_item_connect(), and gen_item_connect().

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

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.

References gen_item_s::all, DEBUG, debug_mode, gen_item_s::elem, gen_item_s::expr, gen_item_stringify(), GI_TYPE_BIND, malloc_safe, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, print_output(), PROFILE, strdup_safe, gen_item_s::suppl, user_msg, USER_MSG_LENGTH, and gen_item_s::varname.

Referenced by db_create_expression(), and gen_item_resolve().

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

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.

References gen_item_s::all, DEBUG, debug_mode, gen_item_s::elem, gen_item_s::expr, gen_item_stringify(), GI_TYPE_EXPR, malloc_safe, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, print_output(), PROFILE, gen_item_s::suppl, user_msg, USER_MSG_LENGTH, and gen_item_s::varname.

Referenced by db_add_expression().

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

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.

References gen_item_s::all, DEBUG, debug_mode, gen_item_s::elem, gen_item_stringify(), GI_TYPE_INST, gen_item_s::inst, malloc_safe, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, print_output(), PROFILE, gen_item_s::suppl, user_msg, USER_MSG_LENGTH, and gen_item_s::varname.

Referenced by db_add_instance().

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

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.

References gen_item_s::all, DEBUG, debug_mode, gen_item_s::elem, gen_item_stringify(), GI_TYPE_SIG, malloc_safe, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, print_output(), PROFILE, gen_item_s::sig, gen_item_s::suppl, user_msg, USER_MSG_LENGTH, and gen_item_s::varname.

Referenced by db_add_signal(), funit_find_signal(), and gen_item_resolve().

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

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.

References gen_item_s::all, DEBUG, debug_mode, gen_item_s::elem, gen_item_stringify(), GI_TYPE_STMT, malloc_safe, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, print_output(), PROFILE, gen_item_s::stmt, gen_item_s::suppl, user_msg, USER_MSG_LENGTH, and gen_item_s::varname.

Referenced by db_add_statement(), and gen_item_resolve().

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

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.

References gen_item_s::all, DEBUG, debug_mode, gen_item_s::elem, gen_item_stringify(), GI_TYPE_TFN, gen_item_s::inst, malloc_safe, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, print_output(), PROFILE, gen_item_s::suppl, user_msg, USER_MSG_LENGTH, and gen_item_s::varname.

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

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

References gen_item_s::elem, GI_TYPE_SIG, GI_TYPE_STMT, gen_item_s::part, PROFILE, PROFILE_END, gen_item_s::sig, statement_db_write_tree(), gen_item_s::stmt, gen_item_s::suppl, and vsignal_db_write().

Referenced by funit_db_write().

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

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

References gen_item_s::elem, GI_TYPE_STMT, gen_item_s::part, PROFILE, PROFILE_END, statement_db_write_expr_tree(), gen_item_s::stmt, and gen_item_s::suppl.

Referenced by funit_db_write().

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

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

References gen_item_s::elem, gen_item_s::expr, expression_dealloc(), FALSE, free_safe, gen_item_dealloc(), GI_TYPE_BIND, GI_TYPE_EXPR, GI_TYPE_INST, GI_TYPE_SIG, GI_TYPE_STMT, GI_TYPE_TFN, gen_item_s::inst, instance_dealloc_tree(), gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, PROFILE, PROFILE_END, gen_item_s::sig, statement_dealloc_recursive(), gen_item_s::stmt, gen_item_s::suppl, gen_item_s::varname, and vsignal_dealloc().

Referenced by db_find_gen_item(), funit_find_signal(), gen_item_dealloc(), and gitem_link_delete_list().

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

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

References gen_item_stringify(), PROFILE, and PROFILE_END.

Referenced by gen_item_display_block_helper().

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 }

int gen_item_display_block ( gen_item root  ) 

Displays an entire generate block.

Returns:
Returns a value of 1 so that this function can be called within an expression.

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

Parameters:
root Pointer to starting generate item to display

References gen_item_display_block_helper(), PROFILE, and PROFILE_END.

Referenced by gitem_link_display().

00189   { PROFILE(GEN_ITEM_DISPLAY_BLOCK);
00190 
00191   printf( "Generate block:\n" );
00192 
00193   gen_item_display_block_helper( root );
00194 
00195   PROFILE_END;
00196 
00197   return( 1 );
00198 
00199 }

static 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

References gen_item_display(), gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, PROFILE, PROFILE_END, and gen_item_s::suppl.

Referenced by gen_item_display_block().

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

References gen_item_compare(), gen_item_find(), gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, PROFILE, PROFILE_END, and gen_item_s::suppl.

Referenced by db_find_gen_item(), funit_find_signal(), gen_item_find(), and gitem_link_find().

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

static 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

References PROFILE, and PROFILE_END.

Referenced by gen_item_calc_signal_name(), and gen_item_varname_contains_genvar().

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

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

References gen_item_s::elem, gen_item_remove_if_contains_expr_calling_stmt(), GI_TYPE_STMT, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, PROFILE, PROFILE_END, statement_contains_expr_calling_stmt(), gen_item_s::stmt, and gen_item_s::suppl.

Referenced by gen_item_remove_if_contains_expr_calling_stmt(), and instance_remove_stmt_blks_calling_stmt().

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

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

References gen_item_s::elem, gen_item_resize_stmts_and_sigs(), GI_TYPE_SIG, GI_TYPE_STMT, gen_item_s::next_false, gen_item_s::next_true, gen_item_s::part, PROFILE, PROFILE_END, gen_item_s::sig, statement_size_elements(), gen_item_s::stmt, gen_item_s::suppl, and vsignal_create_vec().

Referenced by funit_size_elements(), and gen_item_resize_stmts_and_sigs().

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

static 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

References bind_add(), curr_db, DEBUG, debug_mode, gen_item_s::elem, ESUPPL_IS_TRUE, expression_s::exec_num, EXP_OP_DISABLE, EXP_OP_FUNC_CALL, EXP_OP_NB_CALL, EXP_OP_TASK_CALL, gen_item_s::expr, expression_operate_recursively(), expression_resize(), FALSE, FATAL, free_safe, funit_link_s::funit, funit_inst_s::funit, funit_dealloc(), FUNIT_FUNCTION, db_s::funit_head, funit_link_find(), FUNIT_MODULE, FUNIT_NAMED_BLOCK, FUNIT_TASK, gen_item_calc_signal_name(), gen_item_create_bind(), gen_item_create_sig(), gen_item_create_stmt(), gen_item_stringify(), GI_TYPE_BIND, GI_TYPE_EXPR, GI_TYPE_INST, GI_TYPE_SIG, GI_TYPE_STMT, GI_TYPE_TFN, funit_inst_s::gitem_head, gitem_link_add(), funit_inst_s::gitem_tail, gen_item_s::inst, db_s::inst_head, inst_link_find_by_funit(), inst_parm_add_genvar(), instance_copy(), instance_find_scope(), instance_parse_add(), expression_s::line, malloc_safe, func_unit_s::name, funit_inst_s::name, gen_item_s::next_false, gen_item_s::next_true, obf_funit, obf_inst, obf_sig, expression_s::op, param_resolve_inst(), gen_item_s::part, print_output(), PROFILE, PROFILE_END, funit_inst_s::range, scope_find_signal(), gen_item_s::sig, gen_item_s::stmt, expression_s::suppl, gen_item_s::suppl, Throw, TRUE, func_unit_s::type, user_msg, USER_MSG_LENGTH, vsignal_s::value, gen_item_s::varname, and vector_to_int().

Referenced by generate_resolve_inst().

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

static 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

References gen_item_s::all, gen_item_s::elem, statement_s::exp, gen_item_s::expr, expression_string(), free_safe, funit_inst_s::funit, get_funit_type(), GI_TYPE_BIND, GI_TYPE_EXPR, GI_TYPE_INST, GI_TYPE_SIG, GI_TYPE_STMT, GI_TYPE_TFN, expression_s::id, gen_item_s::inst, expression_s::line, malloc_safe_nolimit, funit_inst_s::name, vsignal_s::name, gen_item_s::next_false, gen_item_s::next_true, obf_inst, obf_sig, gen_item_s::part, PROFILE, PROFILE_END, gen_item_s::sig, gen_item_s::stmt, gen_item_s::suppl, func_unit_s::type, and gen_item_s::varname.

Referenced by gen_item_create_bind(), gen_item_create_expr(), gen_item_create_inst(), gen_item_create_sig(), gen_item_create_stmt(), gen_item_create_tfn(), gen_item_display(), and gen_item_resolve().

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.

References FALSE, free_safe, gen_item_get_genvar(), PROFILE, strdup_safe, and TRUE.

Referenced by db_create_expression().

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

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

References curr_db, FALSE, generate_remove_stmt_helper(), inst_link_s::inst, db_s::inst_head, inst_link_s::next, PROFILE, and PROFILE_END.

Referenced by stmt_blk_add_to_remove_list().

01155   { PROFILE(GENERATE_REMOVE_STMT);
01156 
01157   bool       retval = FALSE;  /* Return value for this function */
01158   inst_link* instl;           /* Pointer to current instance list to parse */
01159 
01160   /* Search for the generate item in the instance lists */
01161   instl = db_list[curr_db]->inst_head;
01162   while( instl != NULL ) {
01163     retval |= generate_remove_stmt_helper( instl->inst, stmt );
01164     instl = instl->next;
01165   }
01166 
01167   PROFILE_END;
01168 
01169   return( retval );
01170 
01171 }

static 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

References funit_inst_s::child_head, gen_item_s::elem, statement_s::exp, FALSE, gitem_link_s::gi, GI_TYPE_STMT, funit_inst_s::gitem_head, expression_s::id, funit_inst_s::next, gitem_link_s::next, gen_item_s::part, PROFILE, PROFILE_END, statement_find_statement(), gen_item_s::stmt, gen_item_s::suppl, and TRUE.

Referenced by generate_remove_stmt().

01117   { PROFILE(GENERATE_REMOVE_STMT_HELPER);
01118 
01119   bool        retval   = FALSE;  /* Return value for this function */
01120   funit_inst* curr_child;        /* Pointer to current child to search */
01121   gitem_link* gil;               /* Pointer to generate item link */
01122 
01123   /* Remove the generate item from the current instance if it exists there */
01124   gil = root->gitem_head;
01125   while( gil != NULL ) {
01126     if( (gil->gi->suppl.part.type == GI_TYPE_STMT) && (statement_find_statement( gil->gi->elem.stmt, stmt->exp->id ) != NULL) ) {
01127       gil->gi->suppl.part.removed = 1;
01128       retval = TRUE;
01129     }
01130     gil = gil->next;
01131   }
01132 
01133   /* Search child instances */
01134   curr_child = root->child_head;
01135   while( curr_child != NULL ) {
01136     retval |= generate_remove_stmt_helper( curr_child, stmt );
01137     curr_child = curr_child->next;
01138   }
01139 
01140   PROFILE_END;
01141 
01142   return( retval );
01143 
01144 }

void generate_resolve_inst ( funit_inst inst  ) 

Resolves all generate items in the design.

Exceptions:
anonymous generate_resolve gen_item_resolve

Resolves all generate items in the given instance. This is called at a specific point in the binding process.

Parameters:
inst Pointer to current instance in instance tree to resolve for

References funit_inst_s::funit, gen_item_resolve(), gitem_link_s::gi, func_unit_s::gitem_head, gitem_link_s::next, PROFILE, and PROFILE_END.

Referenced by instance_resolve_helper().

01092   { PROFILE(GENERATE_RESOLVE_INST);
01093 
01094   if( inst != NULL ) {
01095 
01096     /* Resolve ourself */
01097     if( inst->funit != NULL ) {
01098       gitem_link* curr_gi = inst->funit->gitem_head;
01099       while( curr_gi != NULL ) {
01100         gen_item_resolve( curr_gi->gi, inst );
01101         curr_gi = curr_gi->next;
01102       }
01103     }
01104 
01105   }
01106 
01107   PROFILE_END;
01108 
01109 }

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.

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

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

Array of database pointers storing all currently loaded databases.

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 Sun Nov 21 00:55:39 2010 for Covered by  doxygen 1.6.3