#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_item * | gen_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_item * | gen_item_create_expr (expression *expr) |
| Creates a generate item for an expression. | |
| gen_item * | gen_item_create_sig (vsignal *sig) |
| Creates a generate item for a signal. | |
| gen_item * | gen_item_create_stmt (statement *stmt) |
| Creates a generate item for a statement. | |
| gen_item * | gen_item_create_inst (funit_inst *inst) |
| Creates a generate item for an instance. | |
| gen_item * | gen_item_create_tfn (funit_inst *inst) |
| Creates a generate item for a namespace. | |
| gen_item * | gen_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_unit * | curr_funit |
| int | curr_sig_id |
|
||||||||||||
|
Assigns unique signal ID or expression IDs to all expressions for specified statement block.
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 }
|
|
|
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.
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 }
|
|
||||||||||||||||||||
|
Returns the actual signal name specified by the given signal name which references a generated hierarchy.
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
Connects a generate item block to a new generate item.
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 }
|
|
||||||||||||
|
Creates a generate item for a binding.
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 }
|
|
|
Creates a 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 }
|
|
|
Creates a 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 }
|
|
|
Creates a 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 }
|
|
|
Creates a 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 }
|
|
|
Creates a 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 }
|
|
||||||||||||||||
|
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.
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 }
|
|
||||||||||||
|
Outputs the entire expression tree from the given generate statement. Outputs all expressions for the statement contained in the specified generate item.
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 }
|
|
||||||||||||
|
Deallocates all associated memory for the given generate item. Recursively deallocates the gen_item structure tree.
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 }
|
|
|
Displays the specified generate item to standard output. Displays the contents of the specified generate item to standard output (used for debugging purposes).
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 }
|
|
|
Displays an entire generate block. Displays an entire generate block to standard output (used for debugging purposes).
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 }
|
|
|
Displays an entire generate block to standard output (used for debugging purposes).
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 }
|
|
||||||||||||
|
Searches for a generate item in the generate block of root that matches gi.
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 }
|
|
||||||||||||||||||||
|
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 ']'.
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 }
|
|
||||||||||||
|
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.
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 }
|
|
||||||||||||
|
Resizes all statements and signals in the given generate item block.
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
Creates a user-readable version of the specified generate item and stores it in the specified 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 }
|
|
|
Returns TRUE if the specified variable name contains a generate variable within it.
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 }
|
|
|
Removes the given generate statement from the correct instance.
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 }
|
|
||||||||||||
|
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 }
|
|
|
Resolves all generate items in the design.
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 }
|
|
||||||||||||||||||||
|
|
|
|
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. |
|
|
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. |
1.3.4