Contains functions for handling functional units. More...
#include <stdio.h>
#include "defines.h"
Go to the source code of this file.
Functions | |
func_unit * | funit_create () |
Creates new functional unit from heap and initializes structure. | |
func_unit * | funit_get_curr_module (func_unit *funit) |
Returns the parent module of the given functional unit. | |
const func_unit * | funit_get_curr_module_safe (const func_unit *funit) |
Returns the parent module of the given functional unit (returning a const version). | |
func_unit * | funit_get_curr_function (func_unit *funit) |
Returns the parent function of the given functional unit (if there is one). | |
func_unit * | funit_get_curr_task (func_unit *funit) |
Returns the parent task of the given functional unit (if there is one). | |
int | funit_get_port_count (func_unit *funit) |
Returns the number of input, output and inout ports in the specified functional unit. | |
mod_parm * | funit_find_param (char *name, func_unit *funit) |
Finds specified module parameter given the current functional unit and its scope. | |
vsignal * | funit_find_signal (char *name, func_unit *funit) |
Finds specified signal given in the current functional unit. | |
void | funit_remove_stmt_blks_calling_stmt (func_unit *funit, statement *stmt) |
Finds all expressions that call the given statement. | |
char * | funit_gen_task_function_namedblock_name (char *orig_name, func_unit *parent) |
Generates the internally used task/function/named-block name for the specified functional unit. | |
void | funit_size_elements (func_unit *funit, funit_inst *inst, bool gen_all, bool alloc_exprs) |
Sizes all elements for the current functional unit from the given instance. | |
void | funit_db_write (func_unit *funit, char *scope, bool name_diff, FILE *file, funit_inst *inst, bool ids_issued) |
Writes contents of provided functional unit to specified output. | |
void | funit_db_read (func_unit *funit, char *scope, bool *name_diff, char **line) |
Read contents of current line from specified file, creates functional unit and adds to functional unit list. | |
void | funit_version_db_read (func_unit *funit, char **line) |
Reads the functional unit version information from the functional unit line and adds it to the current functional unit. | |
void | funit_db_inst_merge (func_unit *base, FILE *file, bool same) |
Performs an instance merge with the given base functional unit. | |
void | funit_db_mod_merge (func_unit *base, FILE *file, bool same) |
Performs a module merge with the given base functional unit. | |
void | funit_merge (func_unit *base, func_unit *other) |
Merges two functional units into the base functional unit. | |
void | funit_db_merge (func_unit *base, FILE *file, bool same) |
Reads and merges two functional units into base functional unit. | |
char * | funit_flatten_name (func_unit *funit) |
Flattens the functional unit name by removing all unnamed scope portions. | |
func_unit * | funit_find_by_id (int id) |
Finds the functional unit that contains the given statement/expression ID. | |
bool | funit_is_top_module (func_unit *funit) |
Returns TRUE if the given functional unit does not contain any input, output or inout ports. | |
bool | funit_is_unnamed (func_unit *funit) |
Returns TRUE if the given functional unit is an unnamed scope. | |
bool | funit_is_unnamed_child_of (func_unit *parent, func_unit *child) |
Returns TRUE if the specified "parent" functional unit is a parent of the "child" functional unit. | |
bool | funit_is_child_of (func_unit *parent, func_unit *child) |
Returns TRUE if the specified "parent" functional unit is a parent of the "child" functional unit. | |
void | funit_display_signals (func_unit *funit) |
Displays signals stored in this functional unit. | |
void | funit_display_expressions (func_unit *funit) |
Displays expressions stored in this functional unit. | |
void | funit_add_thread (func_unit *funit, thread *thr) |
Adds given thread to functional unit's thread pointer/thread pointer list. | |
void | funit_push_threads (func_unit *funit, const statement *stmt, const sim_time *time) |
Pushes the threads associated with the given functional unit onto the active simulation queue. | |
void | funit_delete_thread (func_unit *funit, thread *thr) |
Removes given thread from the given functional unit's thread pointer/thread pointer list. | |
void | funit_output_dumpvars (FILE *vfile, func_unit *funit, const char *scope) |
Outputs dumpvars calls to the given file. | |
bool | funit_is_one_signal_assigned (func_unit *funit) |
Returns TRUE if at least one signal was found that needs to be assigned by the dumpfile. | |
void | funit_dealloc (func_unit *funit) |
Deallocates functional unit element from heap. |
Contains functions for handling functional units.
Adds given thread to functional unit's thread pointer/thread pointer list.
funit | Pointer to functional unit to add given thread pointer to | |
thr | Pointer to thread associated with this statement |
Adds the given thread to the given functional unit's thread/thread list element pointer, allocating memory as needed and adjusting values as needed.
References func_unit_s::elem, func_unit_s::elem_type, thr_list_s::head, malloc_safe, thr_list_s::next, thr_link_s::next, PROFILE, thr_list_s::tail, thr_link_s::thr, func_unit_s::thr, and func_unit_s::tlist.
Referenced by sim_create_thread().
01414 { PROFILE(STATEMENT_ADD_THREAD); 01415 01416 assert( funit != NULL ); 01417 assert( thr != NULL ); 01418 01419 /* Statement element should point to a thread */ 01420 if( funit->elem_type == 0 ) { 01421 01422 /* If the statement element currently points to nothing, simply point the statement element to the given thread */ 01423 if( funit->elem.thr == NULL ) { 01424 funit->elem.thr = thr; 01425 01426 /* Otherwise, change the type to a thread list, create a thread list, initialize it and continue */ 01427 } else { 01428 01429 thr_list* tlist; /* Pointer to thread list */ 01430 01431 /* Allocate memory for the thread list */ 01432 tlist = (thr_list*)malloc_safe( sizeof( thr_list ) ); 01433 01434 /* Create new thread link for existing thread */ 01435 tlist->head = (thr_link*)malloc_safe( sizeof( thr_link ) ); 01436 tlist->head->thr = funit->elem.thr; 01437 01438 /* Create new thread link for specified thread */ 01439 tlist->tail = (thr_link*)malloc_safe( sizeof( thr_link ) ); 01440 tlist->tail->thr = thr; 01441 tlist->tail->next = NULL; 01442 tlist->head->next = tlist->tail; 01443 01444 /* Specify the next pointer to be NULL (to indicate that there aren't any available thread links to use) */ 01445 tlist->next = NULL; 01446 01447 /* Repopulate the functional unit */ 01448 funit->elem.tlist = tlist; 01449 funit->elem_type = 1; 01450 01451 } 01452 01453 /* Otherwise, the statement element is a pointer to a thread list already */ 01454 } else { 01455 01456 /* If there are no thread links already allocated and available, allocate a new thread link */ 01457 if( funit->elem.tlist->next == NULL ) { 01458 01459 thr_link* thrl; /* Pointer to a thread link */ 01460 01461 /* Allocate and initialize thread link */ 01462 thrl = (thr_link*)malloc_safe( sizeof( thr_link ) ); 01463 thrl->thr = thr; 01464 thrl->next = NULL; 01465 01466 /* Add the new thread link to the list */ 01467 funit->elem.tlist->tail->next = thrl; 01468 funit->elem.tlist->tail = thrl; 01469 01470 /* Otherwise, use the link pointed at by next and adjust next */ 01471 } else { 01472 01473 funit->elem.tlist->next->thr = thr; 01474 funit->elem.tlist->next = funit->elem.tlist->next->next; 01475 01476 } 01477 01478 } 01479 01480 }
func_unit* funit_create | ( | ) |
Creates new functional unit from heap and initializes structure.
Allocates memory from the heap for a functional unit element and initializes all contents to NULL. Returns a pointer to the newly created functional unit.
References funit_init(), malloc_safe, PROFILE, and PROFILE_END.
Referenced by db_add_instance(), db_read(), and search_init().
00113 { PROFILE(FUNIT_CREATE); 00114 00115 func_unit* funit; /* Pointer to newly created functional unit element */ 00116 00117 /* Create and initialize functional unit */ 00118 funit = (func_unit*)malloc_safe( sizeof( func_unit ) ); 00119 00120 funit_init( funit ); 00121 00122 PROFILE_END; 00123 00124 return( funit ); 00125 00126 }
Performs an instance merge with the given base functional unit.
anonymous | fsm_db_merge Throw Throw expression_db_merge vsignal_db_merge |
Parses specified line for functional unit information and performs a merge of the two specified functional units, placing the resulting merge functional unit into the functional unit named base. If there are any differences between the two functional units, a warning or error will be displayed to the user.
base | Module that will merge in that data from the in functional unit | |
file | Pointer to CDD file handle to read | |
same | Specifies if functional unit to be merged should match existing functional unit exactly or not |
References Catch_anonymous, DB_TYPE_EXPRESSION, DB_TYPE_FSM, DB_TYPE_FUNIT_VERSION, DB_TYPE_RACE, DB_TYPE_SIGNAL, DB_TYPE_STATEMENT, exp_link_s::exp, func_unit_s::exp_head, expression_db_merge(), FATAL, free_safe, fsm_db_merge(), func_unit_s::fsm_head, FUNIT_MODULE, func_unit_s::name, race_blk_s::next, fsm_link_s::next, stmt_link_s::next, sig_link_s::next, exp_link_s::next, print_output(), PROFILE, PROFILE_END, func_unit_s::race_head, sig_link_s::sig, func_unit_s::sig_head, func_unit_s::stmt_head, fsm_link_s::table, Throw, Try, func_unit_s::type, util_readline(), func_unit_s::version, and vsignal_db_merge().
Referenced by db_read().
00776 { PROFILE(FUNIT_DB_INST_MERGE); 00777 00778 exp_link* curr_base_exp; /* Pointer to current expression in base functional unit expression list */ 00779 sig_link* curr_base_sig; /* Pointer to current signal in base functional unit signal list */ 00780 stmt_link* curr_base_stmt; /* Statement list iterator */ 00781 fsm_link* curr_base_fsm; /* Pointer to current FSM in base functional unit FSM list */ 00782 race_blk* curr_base_race; /* Pointer to current race condition block in base module list */ 00783 char* curr_line; /* Pointer to current line being read from CDD */ 00784 unsigned int curr_line_size; /* Number of bytes allocated for curr_line */ 00785 char* rest_line; /* Pointer to rest of read line */ 00786 int type; /* Specifies currently read CDD type */ 00787 int chars_read; /* Number of characters read from current CDD line */ 00788 00789 assert( base != NULL ); 00790 assert( base->name != NULL ); 00791 00792 /* Handle the functional unit version, if specified */ 00793 if( base->version != NULL ) { 00794 if( util_readline( file, &curr_line, &curr_line_size ) ) { 00795 Try { 00796 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 00797 rest_line = curr_line + chars_read; 00798 if( type == DB_TYPE_FUNIT_VERSION ) { 00799 while( *rest_line == ' ' ) rest_line++; 00800 if( strcmp( base->version, rest_line ) != 0 ) { 00801 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00802 Throw 0; 00803 } 00804 } else { 00805 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00806 Throw 0; 00807 } 00808 } else { 00809 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00810 Throw 0; 00811 } 00812 } Catch_anonymous { 00813 free_safe( curr_line, curr_line_size ); 00814 Throw 0; 00815 } 00816 } else { 00817 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00818 Throw 0; 00819 } 00820 } 00821 00822 /* Handle all functional unit expressions */ 00823 curr_base_exp = base->exp_head; 00824 while( curr_base_exp != NULL ) { 00825 if( util_readline( file, &curr_line, &curr_line_size ) ) { 00826 Try { 00827 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 00828 rest_line = curr_line + chars_read; 00829 if( type == DB_TYPE_EXPRESSION ) { 00830 expression_db_merge( curr_base_exp->exp, &rest_line, same ); 00831 } else { 00832 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00833 Throw 0; 00834 } 00835 } else { 00836 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00837 Throw 0; 00838 } 00839 } Catch_anonymous { 00840 free_safe( curr_line, curr_line_size ); 00841 Throw 0; 00842 } 00843 free_safe( curr_line, curr_line_size ); 00844 } else { 00845 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00846 Throw 0; 00847 } 00848 curr_base_exp = curr_base_exp->next; 00849 } 00850 00851 /* Handle all functional unit signals */ 00852 curr_base_sig = base->sig_head; 00853 while( curr_base_sig != NULL ) { 00854 if( util_readline( file, &curr_line, &curr_line_size ) ) { 00855 Try { 00856 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 00857 rest_line = curr_line + chars_read; 00858 if( type == DB_TYPE_SIGNAL ) { 00859 vsignal_db_merge( curr_base_sig->sig, &rest_line, same ); 00860 } else { 00861 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00862 Throw 0; 00863 } 00864 } else { 00865 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00866 Throw 0; 00867 } 00868 } Catch_anonymous { 00869 free_safe( curr_line, curr_line_size ); 00870 Throw 0; 00871 } 00872 free_safe( curr_line, curr_line_size ); 00873 } else { 00874 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00875 Throw 0; 00876 } 00877 curr_base_sig = curr_base_sig->next; 00878 } 00879 00880 /* Since statements don't get merged, we will just read these lines in */ 00881 curr_base_stmt = base->stmt_head; 00882 while( curr_base_stmt != NULL ) { 00883 if( util_readline( file, &curr_line, &curr_line_size ) ) { 00884 Try { 00885 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 00886 rest_line = curr_line + chars_read; 00887 if( type != DB_TYPE_STATEMENT ) { 00888 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00889 Throw 0; 00890 } 00891 } else { 00892 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00893 Throw 0; 00894 } 00895 } Catch_anonymous { 00896 free_safe( curr_line, curr_line_size ); 00897 Throw 0; 00898 } 00899 free_safe( curr_line, curr_line_size ); 00900 } else { 00901 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00902 Throw 0; 00903 } 00904 curr_base_stmt = curr_base_stmt->next; 00905 } 00906 00907 /* Handle all functional unit FSMs */ 00908 curr_base_fsm = base->fsm_head; 00909 while( curr_base_fsm != NULL ) { 00910 if( util_readline( file, &curr_line, &curr_line_size ) ) { 00911 Try { 00912 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 00913 rest_line = curr_line + chars_read; 00914 if( type == DB_TYPE_FSM ) { 00915 fsm_db_merge( curr_base_fsm->table, &rest_line ); 00916 } else { 00917 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00918 Throw 0; 00919 } 00920 } else { 00921 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00922 Throw 0; 00923 } 00924 } Catch_anonymous { 00925 free_safe( curr_line, curr_line_size ); 00926 Throw 0; 00927 } 00928 free_safe( curr_line, curr_line_size ); 00929 } else { 00930 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00931 Throw 0; 00932 } 00933 curr_base_fsm = curr_base_fsm->next; 00934 } 00935 00936 /* Since race condition blocks don't get merged, we will just read these lines in */ 00937 if( base->type == FUNIT_MODULE ) { 00938 curr_base_race = base->race_head; 00939 while( curr_base_race != NULL ) { 00940 if( util_readline( file, &curr_line, &curr_line_size ) ) { 00941 Try { 00942 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 00943 rest_line = curr_line + chars_read; 00944 if( type != DB_TYPE_RACE ) { 00945 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00946 Throw 0; 00947 } 00948 } else { 00949 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00950 Throw 0; 00951 } 00952 } Catch_anonymous { 00953 free_safe( curr_line, curr_line_size ); 00954 Throw 0; 00955 } 00956 free_safe( curr_line, curr_line_size ); 00957 } else { 00958 print_output( "Databases being merged are incompatible.", FATAL, __FILE__, __LINE__ ); 00959 Throw 0; 00960 } 00961 curr_base_race = curr_base_race->next; 00962 } 00963 } 00964 00965 PROFILE_END; 00966 00967 }
Reads and merges two functional units into base functional unit.
Performs a module merge with the given base functional unit.
anonymous | fsm_db_merge Throw Throw expression_db_merge vsignal_db_merge |
Parses specified line for functional unit information and performs a merge of the two specified functional units, placing the resulting merge functional unit into the functional unit named base. If there are any differences between the two functional units, a warning or error will be displayed to the user.
base | Module that will merge in that data from the in functional unit | |
file | Pointer to CDD file handle to read | |
same | Specifies if functional unit to be merged should match existing functional unit exactly or not |
References Catch_anonymous, DB_TYPE_EXPRESSION, DB_TYPE_FSM, DB_TYPE_FUNIT, DB_TYPE_FUNIT_VERSION, DB_TYPE_RACE, DB_TYPE_SIGNAL, DB_TYPE_STATEMENT, race_blk_s::end_line, exp_link_s::exp, func_unit_s::exp_head, exp_link_find_by_pos(), expression_db_merge(), expression_db_read(), FALSE, FATAL, free_safe, fsm_db_merge(), fsm_db_read(), func_unit_s::fsm_head, fsm_link_find_by_pos(), func_unit_s::name, race_blk_s::next, print_output(), PROFILE, PROFILE_END, race_db_read(), func_unit_s::race_head, READ_MODE_REPORT_MOD_MERGE, race_blk_s::reason, sig_link_s::sig, func_unit_s::sig_head, sig_link_find(), race_blk_s::start_line, statement_db_read(), func_unit_s::stmt_head, stmt_link_find_by_pos(), fsm_link_s::table, Throw, TRUE, Try, util_readline(), vsignal_db_merge(), and vsignal_db_read().
Referenced by db_read().
00981 { PROFILE(FUNIT_DB_MOD_MERGE); 00982 00983 fsm_link* curr_base_fsm; /* Pointer to current FSM in base functional unit FSM list */ 00984 char* curr_line; /* Pointer to current line being read from CDD */ 00985 unsigned int curr_line_size; /* Number of bytes allocated for curr_line */ 00986 char* rest_line; /* Pointer to rest of read line */ 00987 int type; /* Specifies currently read CDD type */ 00988 int chars_read; /* Number of characters read from current CDD line */ 00989 bool new_funit_found = FALSE; 00990 00991 assert( base != NULL ); 00992 assert( base->name != NULL ); 00993 00994 /* Initialize pointers */ 00995 curr_base_fsm = base->fsm_head; 00996 00997 /* Parse the current functional unit in the CDD file */ 00998 while( !new_funit_found && util_readline( file, &curr_line, &curr_line_size ) ) { 00999 01000 if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) { 01001 01002 rest_line = curr_line + chars_read; 01003 01004 Try { 01005 01006 switch( type ) { 01007 01008 case DB_TYPE_FUNIT_VERSION : 01009 /* Do nothing */ 01010 break; 01011 01012 case DB_TYPE_EXPRESSION : 01013 { 01014 int id; 01015 exp_op_type op; 01016 int line; 01017 uint32 col; 01018 if( sscanf( rest_line, "%d %x %d %x", &id, &op, &line, &col ) == 4 ) { 01019 exp_link* expl = exp_link_find_by_pos( op, line, col, base->exp_head ); 01020 if( expl != NULL ) { 01021 expression_db_merge( expl->exp, &rest_line, FALSE ); 01022 } else { 01023 expression_db_read( &rest_line, base, FALSE ); 01024 } 01025 } else { 01026 print_output( "Illegal CDD file format", FATAL, __FILE__, __LINE__ ); 01027 Throw 0; 01028 } 01029 break; 01030 } 01031 01032 case DB_TYPE_SIGNAL : 01033 { 01034 char name[256]; 01035 if( sscanf( rest_line, "%s", name ) == 1 ) { 01036 sig_link* sigl = sig_link_find( name, base->sig_head ); 01037 if( sigl != NULL ) { 01038 vsignal_db_merge( sigl->sig, &rest_line, FALSE ); 01039 } else { 01040 vsignal_db_read( &rest_line, base ); 01041 } 01042 } else { 01043 print_output( "Illegal CDD file format", FATAL, __FILE__, __LINE__ ); 01044 Throw 0; 01045 } 01046 break; 01047 } 01048 01049 case DB_TYPE_STATEMENT : 01050 { 01051 int id; 01052 unsigned int ppline; 01053 uint32 first_col; 01054 if( sscanf( rest_line, "%d %u %u", &id, &ppline, &first_col ) == 3 ) { 01055 stmt_link* stmtl = stmt_link_find_by_pos( ppline, first_col, base->stmt_head ); 01056 if( stmtl == NULL ) { 01057 statement_db_read( &rest_line, base, READ_MODE_REPORT_MOD_MERGE ); 01058 } 01059 } else { 01060 print_output( "Illegal CDD file format", FATAL, __FILE__, __LINE__ ); 01061 Throw 0; 01062 } 01063 break; 01064 } 01065 01066 case DB_TYPE_FSM : 01067 { 01068 int line; 01069 if( sscanf( rest_line, "%d", &line ) == 1 ) { 01070 fsm_link* fsml = fsm_link_find_by_pos( line, base->fsm_head ); 01071 if( fsml == NULL ) { 01072 fsm_db_read( &rest_line, base ); 01073 } else { 01074 fsm_db_merge( curr_base_fsm->table, &rest_line ); 01075 } 01076 } else { 01077 print_output( "Illegal CDD file format", FATAL, __FILE__, __LINE__ ); 01078 Throw 0; 01079 } 01080 break; 01081 } 01082 01083 case DB_TYPE_RACE : 01084 { 01085 int reason; 01086 int start_line; 01087 int end_line; 01088 if( sscanf( rest_line, "%d %d %d", &reason, &start_line, &end_line ) == 3 ) { 01089 race_blk* rb = base->race_head; 01090 while( (rb != NULL) && ((rb->reason != reason) || (rb->start_line != start_line) || (rb->end_line != end_line)) ) { 01091 rb = rb->next; 01092 } 01093 if( rb == NULL ) { 01094 race_db_read( &rest_line, base ); 01095 } 01096 } else { 01097 print_output( "Illegal CDD file format", FATAL, __FILE__, __LINE__ ); 01098 Throw 0; 01099 } 01100 break; 01101 } 01102 01103 /* If the type is a new functional unit, move the current file pointer back to the beginning of the line */ 01104 case DB_TYPE_FUNIT : 01105 { 01106 int rv = fseek( file, (0 - (strlen( curr_line ) + 1)), SEEK_CUR ); 01107 assert( rv == 0 ); 01108 new_funit_found = TRUE; 01109 break; 01110 } 01111 01112 default : 01113 print_output( "Illegal CDD file format", FATAL, __FILE__, __LINE__ ); 01114 Throw 0; 01115 /*@-unreachable@*/ 01116 break; 01117 /*@=unreachable@*/ 01118 01119 } 01120 01121 } Catch_anonymous { 01122 free_safe( curr_line, curr_line_size ); 01123 Throw 0; 01124 } 01125 01126 } 01127 01128 /* Deallocate the current line string */ 01129 free_safe( curr_line, curr_line_size ); 01130 01131 } 01132 01133 PROFILE_END; 01134 01135 }
Read contents of current line from specified file, creates functional unit and adds to functional unit list.
anonymous | Throw |
Reads the current line of the specified file and parses it for a functional unit. If all is successful, returns TRUE; otherwise, returns FALSE.
funit | Pointer to functional unit to read contents into | |
scope | Pointer to name of read functional unit scope | |
name_diff | Will cause the name_diff value of the instance to get set to the same value | |
line | Pointer to current line to parse |
References func_unit_s::end_line, FATAL, func_unit_s::filename, func_unit_s::name, print_output(), PROFILE, PROFILE_END, func_unit_s::start_line, Throw, func_unit_s::timescale, func_unit_s::type, user_msg, and USER_MSG_LENGTH.
Referenced by db_read().
00716 { PROFILE(FUNIT_DB_READ); 00717 00718 int chars_read; /* Number of characters currently read */ 00719 int params; /* Number of parameters in string that were parsed */ 00720 00721 /*@-duplicatequals -formatcode -formattype@*/ 00722 if( (params = sscanf( *line, "%d %s \"%[^\"]\" %d %s %d %d %" FMT64 "u%n", 00723 &(funit->type), funit->name, scope, (int*)name_diff, funit->filename, 00724 &(funit->start_line), &(funit->end_line), &(funit->timescale), &chars_read )) == 8 ) { 00725 /*@=duplicatequals =formatcode =formattype@*/ 00726 00727 *line = *line + chars_read; 00728 00729 } else { 00730 00731 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Internal Error: Incorrect number of parameters for func_unit, should be 7 but is %d\n", 00732 params ); 00733 assert( rv < USER_MSG_LENGTH ); 00734 print_output( user_msg, FATAL, __FILE__, __LINE__ ); 00735 Throw 0; 00736 00737 } 00738 00739 PROFILE_END; 00740 00741 }
void funit_db_write | ( | func_unit * | funit, | |
char * | scope, | |||
bool | name_diff, | |||
FILE * | file, | |||
funit_inst * | inst, | |||
bool | ids_issued | |||
) |
Writes contents of provided functional unit to specified output.
anonymous | funit_size_elements |
Prints the database line for the specified functional unit to the specified database file. If there are any problems with the write, returns FALSE; otherwise, returns TRUE.
funit | Pointer to functional unit to write to output | |
scope | String version of functional unit scope in hierarchy | |
name_diff | Specifies that this instance has an inaccurate way | |
file | Pointer to specified output file to write contents | |
inst | Pointer to the current functional unit instance | |
ids_issued | Specifies if IDs have been issued prior to calling this function |
References curr_db, db_scale_to_precision(), DB_TYPE_FUNIT, DB_TYPE_FUNIT_VERSION, DEBUG, func_unit_s::end_line, func_unit_s::er_head, exclude_db_write(), exp_link_s::exp, func_unit_s::exp_head, expression_db_write(), FALSE, func_unit_s::filename, fsm_db_write(), func_unit_s::fsm_head, funit_inst_s::funit, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, FUNIT_FUNCTION, FUNIT_MODULE, FUNIT_NAMED_BLOCK, FUNIT_NO_SCORE, funit_size_elements(), FUNIT_TASK, db_s::fver_head, gen_item_db_write(), gen_item_db_write_expr_tree(), get_funit_type(), gitem_link_s::gi, GI_TYPE_SIG, GI_TYPE_STMT, funit_inst_s::gitem_head, funit_inst_s::name, func_unit_s::name, exclude_reason_s::next, race_blk_s::next, fsm_link_s::next, stmt_link_s::next, inst_parm_s::next, sig_link_s::next, gitem_link_s::next, exp_link_s::next, obf_funit, param_db_write(), funit_inst_s::param_head, funit_inst_s::parent, print_output(), PROFILE, PROFILE_END, race_db_write(), func_unit_s::race_head, stmt_link_s::rm_stmt, scope_local(), sig_link_s::sig, func_unit_s::sig_head, func_unit_s::start_line, statement_db_write(), stmt_link_s::stmt, func_unit_s::stmt_head, str_link_s::str2, str_link_find(), strdup_safe, fsm_link_s::table, func_unit_s::timescale, TRUE, func_unit_s::type, user_msg, USER_MSG_LENGTH, func_unit_s::version, and vsignal_db_write().
Referenced by instance_db_write().
00532 { PROFILE(FUNIT_DB_WRITE); 00533 00534 sig_link* curr_sig; /* Pointer to current functional unit sig_link element */ 00535 exp_link* curr_exp; /* Pointer to current functional unit exp_link element */ 00536 stmt_link* curr_stmt; /* Statement list iterator */ 00537 inst_parm* curr_parm; /* Pointer to current instance parameter */ 00538 fsm_link* curr_fsm; /* Pointer to current functional unit fsm_link element */ 00539 race_blk* curr_race; /* Pointer to current race condition block */ 00540 #ifndef VPI_ONLY 00541 gitem_link* curr_gi; /* Pointer to current gitem_link element */ 00542 #endif 00543 exclude_reason* curr_er; /* Pointer to current exclude reason element */ 00544 char modname[4096]; /* Name of module */ 00545 char tmp[4096]; /* Temporary string holder */ 00546 str_link* strl; /* Pointer to string link */ 00547 00548 if( funit->type != FUNIT_NO_SCORE ) { 00549 00550 #ifdef DEBUG_MODE 00551 assert( (funit->type == FUNIT_MODULE) || (funit->type == FUNIT_NAMED_BLOCK) || 00552 (funit->type == FUNIT_FUNCTION) || (funit->type == FUNIT_TASK) || 00553 (funit->type == FUNIT_AFUNCTION) || (funit->type == FUNIT_ATASK) || 00554 (funit->type == FUNIT_ANAMED_BLOCK) ); 00555 { 00556 unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Writing %s %s", get_funit_type( funit->type ), obf_funit( funit->name ) ); 00557 assert( rv < USER_MSG_LENGTH ); 00558 print_output( user_msg, DEBUG, __FILE__, __LINE__ ); 00559 } 00560 #endif 00561 00562 /* Calculate module name to display */ 00563 if( scope_local( funit->name ) || (inst == NULL) ) { 00564 strcpy( modname, funit->name ); 00565 } else { 00566 funit_inst* parent_inst = inst->parent; 00567 unsigned int rv; 00568 strcpy( modname, inst->name ); 00569 assert( parent_inst != NULL ); 00570 while( parent_inst->funit->type != FUNIT_MODULE ) { 00571 unsigned int rv = snprintf( tmp, 4096, "%s.%s", parent_inst->name, modname ); 00572 assert( rv < 4096 ); 00573 strcpy( modname, tmp ); 00574 parent_inst = parent_inst->parent; 00575 } 00576 rv = snprintf( tmp, 4096, "%s.%s", parent_inst->funit->name, modname ); 00577 assert( rv < 4096 ); 00578 strcpy( modname, tmp ); 00579 } 00580 00581 /* Size all elements in this functional unit and calculate timescale if we are in parse mode */ 00582 if( inst != NULL ) { 00583 funit_size_elements( funit, inst, TRUE, FALSE ); 00584 funit->timescale = db_scale_to_precision( (uint64)1, funit ); 00585 } 00586 00587 /*@-duplicatequals -formatcode -formattype@*/ 00588 fprintf( file, "%d %d %s \"%s\" %d %s %d %d %" FMT64 "u\n", 00589 DB_TYPE_FUNIT, 00590 funit->type, 00591 modname, 00592 scope, 00593 name_diff, 00594 funit->filename, 00595 funit->start_line, 00596 funit->end_line, 00597 funit->timescale 00598 ); 00599 /*@=duplicatequals =formatcode =formattype@*/ 00600 00601 /* Figure out if a file version exists for this functional unit */ 00602 if( (funit->version == NULL) && ((strl = str_link_find( funit->filename, db_list[curr_db]->fver_head )) != NULL) ) { 00603 funit->version = strdup_safe( strl->str2 ); 00604 } 00605 00606 /* If a version was specified for this functional unit, write it now */ 00607 if( funit->version != NULL ) { 00608 fprintf( file, "%d %s\n", DB_TYPE_FUNIT_VERSION, funit->version ); 00609 } 00610 00611 /* Now print all expressions in functional unit */ 00612 curr_exp = funit->exp_head; 00613 while( curr_exp != NULL ) { 00614 expression_db_write( curr_exp->exp, file, (inst != NULL), ids_issued ); 00615 curr_exp = curr_exp->next; 00616 } 00617 00618 #ifndef VPI_ONLY 00619 /* Now print all expressions within generated statements in functional unit */ 00620 if( inst != NULL ) { 00621 curr_gi = inst->gitem_head; 00622 while( curr_gi != NULL ) { 00623 gen_item_db_write_expr_tree( curr_gi->gi, file ); 00624 curr_gi = curr_gi->next; 00625 } 00626 } 00627 #endif 00628 00629 /* Now print all signals in functional unit */ 00630 curr_sig = funit->sig_head; 00631 while( curr_sig != NULL ) { 00632 vsignal_db_write( curr_sig->sig, file ); 00633 curr_sig = curr_sig->next; 00634 } 00635 00636 /* Now print all parameters in functional unit */ 00637 if( inst != NULL ) { 00638 curr_parm = inst->param_head; 00639 while( curr_parm != NULL ) { 00640 param_db_write( curr_parm, file ); 00641 curr_parm = curr_parm->next; 00642 } 00643 } 00644 00645 #ifndef VPI_ONLY 00646 /* Now print any generated signals in the current instance */ 00647 if( inst != NULL ) { 00648 curr_gi = inst->gitem_head; 00649 while( curr_gi != NULL ) { 00650 gen_item_db_write( curr_gi->gi, GI_TYPE_SIG, file ); 00651 curr_gi = curr_gi->next; 00652 } 00653 } 00654 #endif 00655 00656 /* Now print all statements in functional unit */ 00657 curr_stmt = funit->stmt_head; 00658 while( curr_stmt != NULL ) { 00659 if( curr_stmt->rm_stmt ) { 00660 statement_db_write( curr_stmt->stmt, file, ids_issued ); 00661 } 00662 curr_stmt = curr_stmt->next; 00663 } 00664 00665 #ifndef VPI_ONLY 00666 /* Now print any generated statements in the current instance */ 00667 if( inst != NULL ) { 00668 curr_gi = inst->gitem_head; 00669 while( curr_gi != NULL ) { 00670 gen_item_db_write( curr_gi->gi, GI_TYPE_STMT, file ); 00671 curr_gi = curr_gi->next; 00672 } 00673 } 00674 #endif 00675 00676 /* Now print all FSM structures in functional unit */ 00677 curr_fsm = funit->fsm_head; 00678 while( curr_fsm != NULL ) { 00679 fsm_db_write( curr_fsm->table, file, ids_issued ); 00680 curr_fsm = curr_fsm->next; 00681 } 00682 00683 /* Now print all race condition block structures in functional unit (if we are a module) */ 00684 if( funit->type == FUNIT_MODULE ) { 00685 curr_race = funit->race_head; 00686 while( curr_race != NULL ) { 00687 race_db_write( curr_race, file ); 00688 curr_race = curr_race->next; 00689 } 00690 } 00691 00692 /* Now print all of the exclusion reasons in the functional unit */ 00693 curr_er = funit->er_head; 00694 while( curr_er != NULL ) { 00695 exclude_db_write( curr_er, file ); 00696 curr_er = curr_er->next; 00697 } 00698 00699 } 00700 00701 PROFILE_END; 00702 00703 }
void funit_dealloc | ( | func_unit * | funit | ) |
Deallocates functional unit element from heap.
Deallocates functional unit; name and filename strings; and finally the structure itself from the heap.
funit | Pointer to functional unit element to deallocate |
References free_safe, funit_clean(), PROFILE, and PROFILE_END.
Referenced by db_add_instance(), db_read(), funit_link_delete_list(), funit_link_remove(), and gen_item_resolve().
01760 { PROFILE(FUNIT_DEALLOC); 01761 01762 if( funit != NULL ) { 01763 01764 /* Deallocate the contents of the functional unit itself */ 01765 funit_clean( funit ); 01766 01767 /* Deallocate functional unit element itself */ 01768 free_safe( funit, sizeof( func_unit ) ); 01769 01770 } 01771 01772 PROFILE_END; 01773 01774 }
Removes given thread from the given functional unit's thread pointer/thread pointer list.
Searches the given functional unit thread element for the given thread. When the thread is found, its corresponding thread link is moved to the end of the thread list, the next pointer is updated accordingly and the thread pointer is set to NULL. This function will be called whenever a thread is killed in the simulator.
funit | Pointer to functional unit to delete thread from thread pointer/thread list | |
thr | Pointer to thread to remove from the given statement |
References func_unit_s::elem, func_unit_s::elem_type, thr_list_s::head, thr_list_s::next, thr_link_s::next, PROFILE, PROFILE_END, thr_list_s::tail, thr_link_s::thr, func_unit_s::thr, and func_unit_s::tlist.
Referenced by sim_kill_thread().
01520 { PROFILE(STATEMENT_DELETE_THREAD); 01521 01522 assert( funit != NULL ); 01523 assert( thr != NULL ); 01524 01525 /* If the statement element type is a thread pointer, simply clear the thread pointer */ 01526 if( funit->elem_type == 0 ) { 01527 funit->elem.thr = NULL; 01528 01529 /* Otherwise, find the given thread in the statement thread list and remove it */ 01530 } else { 01531 01532 thr_link* curr = funit->elem.tlist->head; 01533 thr_link* last = NULL; 01534 01535 /* Search the thread list for the matching thread */ 01536 while( (curr != NULL) && (curr->thr != thr) ) { 01537 last = curr; 01538 curr = curr->next; 01539 } 01540 01541 /* We should have found the thread in the statement list */ 01542 assert( curr != NULL ); 01543 01544 /* Move this thread link to the end of the thread link list and clear out its values */ 01545 if( funit->elem.tlist->tail != curr ) { 01546 if( funit->elem.tlist->head == curr ) { 01547 funit->elem.tlist->head = curr->next; 01548 } else { 01549 last->next = curr->next; 01550 } 01551 funit->elem.tlist->tail->next = curr; 01552 funit->elem.tlist->tail = curr; 01553 curr->next = NULL; 01554 } 01555 01556 /* Clear the thread pointer */ 01557 curr->thr = NULL; 01558 01559 /* If the thread list next pointer is NULL, set it to the freed thread link structure */ 01560 if( funit->elem.tlist->next == NULL ) { 01561 funit->elem.tlist->next = curr; 01562 } 01563 01564 } 01565 01566 PROFILE_END; 01567 01568 }
void funit_display_expressions | ( | func_unit * | funit | ) |
Displays expressions stored in this functional unit.
funit | Pointer to functional unit element to display expressions |
Iterates through expression list of specified functional unit, displaying each expression's id.
References exp_link_s::exp, func_unit_s::exp_head, expression_display(), get_funit_type(), func_unit_s::name, exp_link_s::next, obf_funit, PROFILE, PROFILE_END, and func_unit_s::type.
01388 { PROFILE(FUNIT_DISPLAY_EXPRESSIONS); 01389 01390 exp_link* expl; /* Pointer to current expression link element */ 01391 01392 printf( "%s => %s", get_funit_type( funit->type ), obf_funit( funit->name ) ); 01393 01394 expl = funit->exp_head; 01395 while( expl != NULL ) { 01396 expression_display( expl->exp ); 01397 expl = expl->next; 01398 } 01399 01400 PROFILE_END; 01401 01402 }
void funit_display_signals | ( | func_unit * | funit | ) |
Displays signals stored in this functional unit.
funit | Pointer to functional unit element to display signals. |
Iterates through signal list of specified functional unit, displaying each signal's name, width, lsb and value.
References get_funit_type(), func_unit_s::name, sig_link_s::next, obf_funit, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, func_unit_s::type, and vsignal_display().
01366 { PROFILE(FUNIT_DISPLAY_SIGNALS); 01367 01368 sig_link* sigl; /* Pointer to current signal link element */ 01369 01370 printf( "%s => %s", get_funit_type( funit->type ), obf_funit( funit->name ) ); 01371 01372 sigl = funit->sig_head; 01373 while( sigl != NULL ) { 01374 vsignal_display( sigl->sig ); 01375 sigl = sigl->next; 01376 } 01377 01378 PROFILE_END; 01379 01380 }
func_unit* funit_find_by_id | ( | int | id | ) |
Finds the functional unit that contains the given statement/expression ID.
Searches the functional units until one is found that contains the expression/statement identified by the specified ID and returns a pointer to this functional unit. If no such ID exists in the design, a value of NULL is returned to the calling statement.
id | Expression/statement ID to search for |
References curr_db, func_unit_s::exp_head, exp_link_find(), funit_link_s::funit, db_s::funit_head, funit_link_s::next, PROFILE, and PROFILE_END.
Referenced by combination_get_coverage(), combination_get_expression(), stmt_blk_add_to_remove_list(), and stmt_blk_remove().
01241 { PROFILE(FUNIT_FIND_BY_ID); 01242 01243 funit_link* funitl; /* Temporary pointer to functional unit link */ 01244 exp_link* expl = NULL; /* Temporary pointer to expression link */ 01245 01246 funitl = db_list[curr_db]->funit_head; 01247 while( (funitl != NULL) && (expl == NULL) ) { 01248 if( (expl = exp_link_find( id, funitl->funit->exp_head )) == NULL ) { 01249 funitl = funitl->next; 01250 } 01251 } 01252 01253 PROFILE_END; 01254 01255 return( (funitl == NULL) ? NULL : funitl->funit ); 01256 01257 }
Finds specified module parameter given the current functional unit and its scope.
Recursively searches from the current functional unit up through its scope until either the parameter is found or until we have exhausted the scope.
name | Name of parameter to search for | |
funit | Functional unit to check for existence of named parameter |
References funit_find_param(), mod_parm_find(), func_unit_s::param_head, func_unit_s::parent, PROFILE, and PROFILE_END.
Referenced by funit_find_param(), and scope_find_param().
00252 { PROFILE(FUNIT_FIND_PARAM); 00253 00254 mod_parm* mparm = NULL; /* Pointer to found module parameter */ 00255 00256 if( funit != NULL ) { 00257 00258 if( (mparm = mod_parm_find( name, funit->param_head )) == NULL ) { 00259 mparm = funit_find_param( name, funit->parent ); 00260 } 00261 00262 } 00263 00264 PROFILE_END; 00265 00266 return( mparm ); 00267 00268 }
Finds specified signal given in the current functional unit.
Searches the signal list in the given functional unit for the specified signal name. If it isn't found there, we look in the generate item list for the same signal.
name | Name of the signal that we are searching for | |
funit | Pointer to functional unit to search in |
References gen_item_s::elem, FALSE, gen_item_create_sig(), gen_item_dealloc(), gen_item_find(), gitem_link_s::gi, func_unit_s::gitem_head, gitem_link_find(), vsignal_s::name, PROFILE, PROFILE_END, gen_item_s::sig, sig_link_s::sig, func_unit_s::sig_head, and sig_link_find().
Referenced by scope_find_signal().
00280 { PROFILE(FUNIT_FIND_SIGNAL); 00281 00282 vsignal* found_sig = NULL; /* Pointer to the found signal */ 00283 vsignal sig; /* Holder for signal to search for */ 00284 sig_link* sigl; /* Pointer to signal link */ 00285 #ifndef VPI_ONLY 00286 gen_item* gi; /* Pointer to temporary generate item */ 00287 gen_item* found_gi; /* Pointer to found generate item */ 00288 gitem_link* gil; /* Pointer to found generate item link */ 00289 #endif 00290 00291 sig.name = name; 00292 00293 /* Search for signal in given functional unit signal list */ 00294 if( (sigl = sig_link_find( name, funit->sig_head )) != NULL ) { 00295 00296 found_sig = sigl->sig; 00297 00298 #ifndef VPI_ONLY 00299 } else { 00300 00301 /* If it was not found, search in the functional unit generate item list */ 00302 gi = gen_item_create_sig( &sig ); 00303 00304 if( ((gil = gitem_link_find( gi, funit->gitem_head )) != NULL) && ((found_gi = gen_item_find( gil->gi, gi )) != NULL) ) { 00305 found_sig = found_gi->elem.sig; 00306 } 00307 00308 /* Deallocate temporary generate item */ 00309 gen_item_dealloc( gi, FALSE ); 00310 #endif 00311 00312 } 00313 00314 PROFILE_END; 00315 00316 return( found_sig ); 00317 00318 }
char* funit_flatten_name | ( | func_unit * | funit | ) |
Flattens the functional unit name by removing all unnamed scope portions.
funit | Pointer to functional unit to flatten name |
References db_is_unnamed_scope(), func_unit_s::name, PROFILE, PROFILE_END, and scope_extract_front().
Referenced by assertion_funit_summary(), assertion_funit_verbose(), assertion_instance_verbose(), combination_funit_summary(), combination_funit_verbose(), combination_instance_verbose(), fsm_funit_summary(), fsm_funit_verbose(), fsm_instance_verbose(), line_funit_summary(), line_funit_verbose(), line_instance_verbose(), memory_ae_funit_summary(), memory_funit_verbose(), memory_instance_verbose(), memory_toggle_funit_summary(), ovl_display_verbose(), race_report_summary(), race_report_verbose(), toggle_funit_summary(), toggle_funit_verbose(), and toggle_instance_verbose().
01203 { PROFILE(FUNIT_FLATTEN_NAME); 01204 01205 static char fscope[4096]; /* Flattened scope name */ 01206 char tmp[4096]; /* Temporary string storage */ 01207 char front[4096]; /* First portion of scope name */ 01208 char rest[4096]; /* Last portion of scope name */ 01209 01210 assert( funit != NULL ); 01211 01212 scope_extract_front( funit->name, fscope, rest ); 01213 strcpy( tmp, rest ); 01214 scope_extract_front( tmp, front, rest ); 01215 01216 while( front[0] != '\0' ) { 01217 if( !db_is_unnamed_scope( front ) ) { 01218 strcat( fscope, "." ); 01219 strcat( fscope, front ); 01220 } 01221 strcpy( tmp, rest ); 01222 scope_extract_front( tmp, front, rest ); 01223 } 01224 01225 PROFILE_END; 01226 01227 return fscope; 01228 01229 }
char* funit_gen_task_function_namedblock_name | ( | char * | orig_name, | |
func_unit * | parent | |||
) |
Generates the internally used task/function/named-block name for the specified functional unit.
orig_name | Verilog name of task, function or named-block | |
parent | Pointer to parent functional unit of this functional unit |
References func_unit_s::name, PROFILE, PROFILE_END, and strdup_safe.
Referenced by db_add_function_task_namedblock().
00353 { PROFILE(FUNIT_GEN_TASK_FUNCTION_NAMEDBLOCK_NAME); 00354 00355 char full_name[4096]; /* Container for new name */ 00356 unsigned int rv; /* Return value for snprintf calls */ 00357 00358 assert( parent != NULL ); 00359 assert( orig_name != NULL ); 00360 00361 /* Generate full name to use for the function/task */ 00362 rv = snprintf( full_name, 4096, "%s.%s", parent->name, orig_name ); 00363 assert( rv < 4096 ); 00364 00365 PROFILE_END; 00366 00367 return( strdup_safe( full_name ) ); 00368 00369 }
Returns the parent function of the given functional unit (if there is one).
funit | Functional unit that may be nested in a function |
References FUNIT_AFUNCTION, FUNIT_FUNCTION, FUNIT_MODULE, func_unit_s::parent, PROFILE, PROFILE_END, and func_unit_s::type.
Referenced by db_create_expression().
00177 { PROFILE(FUNIT_GET_CURR_FUNCTION); 00178 00179 assert( funit != NULL ); 00180 00181 while( (funit->type != FUNIT_FUNCTION) && (funit->type != FUNIT_AFUNCTION) && (funit->type != FUNIT_MODULE) ) { 00182 funit = funit->parent; 00183 } 00184 00185 PROFILE_END; 00186 00187 return( ((funit->type == FUNIT_FUNCTION) || (funit->type == FUNIT_AFUNCTION)) ? funit : NULL ); 00188 00189 }
Returns the parent module of the given functional unit.
Traverses up parent list until the FUNIT_MODULE is found (parent should be NULL).
funit | Pointer to functional unit to get its module from |
References func_unit_s::parent, PROFILE, and PROFILE_END.
Referenced by combination_get_expression(), db_add_function_task_namedblock(), db_find_typedef(), exclude_find_expression(), exclude_find_fsm_arc(), exclude_find_signal(), func_iter_add_sig_links(), func_iter_add_stmt_links(), func_iter_count_scopes(), and mod_parm_add().
00135 { PROFILE(FUNIT_GET_CURR_MODULE); 00136 00137 assert( funit != NULL ); 00138 00139 while( funit->parent != NULL ) { 00140 funit = funit->parent; 00141 } 00142 00143 PROFILE_END; 00144 00145 return( funit ); 00146 00147 }
Returns the parent module of the given functional unit (returning a const version).
Traverses up parent list until the FUNIT_MODULE is found (parent should be NULL). Does this in a way that guarantees that the found functional unit will not be modified.
funit | Pointer to functional unit to get its module from |
References func_unit_s::parent, PROFILE, and PROFILE_END.
Referenced by bind_find_sig_name().
00157 { PROFILE(FUNIT_GET_CURR_MODULE_SAFE); 00158 00159 assert( funit != NULL ); 00160 00161 while( funit->parent != NULL ) { 00162 funit = funit->parent; 00163 } 00164 00165 PROFILE_END; 00166 00167 return( funit ); 00168 00169 }
Returns the parent task of the given functional unit (if there is one).
funit | Functional unit that may be nested in a function |
References FUNIT_ATASK, FUNIT_MODULE, FUNIT_TASK, func_unit_s::parent, PROFILE, PROFILE_END, and func_unit_s::type.
00197 { PROFILE(FUNIT_GET_CURR_TASK); 00198 00199 assert( funit != NULL ); 00200 00201 while( (funit->type != FUNIT_TASK) && (funit->type != FUNIT_ATASK) && (funit->type != FUNIT_MODULE) ) { 00202 funit = funit->parent; 00203 } 00204 00205 PROFILE_END; 00206 00207 return( ((funit->type == FUNIT_TASK) || (funit->type == FUNIT_ATASK)) ? funit : NULL ); 00208 00209 }
int funit_get_port_count | ( | func_unit * | funit | ) |
Returns the number of input, output and inout ports in the specified functional unit.
funit | Pointer to functional unit to process |
References sig_link_s::next, ssuppl_u::part, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, SSUPPL_TYPE_INOUT_NET, SSUPPL_TYPE_INOUT_REG, SSUPPL_TYPE_INPUT_NET, SSUPPL_TYPE_INPUT_REG, SSUPPL_TYPE_OUTPUT_NET, SSUPPL_TYPE_OUTPUT_REG, vsignal_s::suppl, and ssuppl_u::type.
Referenced by bind_task_function_namedblock().
00216 { PROFILE(FUNIT_GET_PORT_COUNT); 00217 00218 sig_link* sigl; /* Pointer to current signal link to examine */ 00219 int port_cnt = 0; /* Return value for this function */ 00220 00221 assert( funit != NULL ); 00222 00223 sigl = funit->sig_head; 00224 while( sigl != NULL ) { 00225 if( (sigl->sig->suppl.part.type == SSUPPL_TYPE_INPUT_NET) || 00226 (sigl->sig->suppl.part.type == SSUPPL_TYPE_INPUT_REG) || 00227 (sigl->sig->suppl.part.type == SSUPPL_TYPE_OUTPUT_NET) || 00228 (sigl->sig->suppl.part.type == SSUPPL_TYPE_OUTPUT_REG) || 00229 (sigl->sig->suppl.part.type == SSUPPL_TYPE_INOUT_NET) || 00230 (sigl->sig->suppl.part.type == SSUPPL_TYPE_INOUT_REG) ) { 00231 port_cnt++; 00232 } 00233 sigl = sigl->next; 00234 } 00235 00236 PROFILE_END; 00237 00238 return( port_cnt ); 00239 00240 }
Returns TRUE if the specified "parent" functional unit is a parent of the "child" functional unit.
parent | Potential parent functional unit to check for relationship to child | |
child | Potential child functional unit to check for relationship to parent |
References func_unit_s::parent, PROFILE, and PROFILE_END.
Referenced by sim_kill_thread_with_funit().
Returns TRUE if at least one signal was found that needs to be assigned by the dumpfile.
funit | Pointer to functional unit to check |
References vsignal_s::exp_head, sig_link_s::next, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, and SIGNAL_ASSIGN_FROM_DUMPFILE.
Referenced by db_check_dumpfile_scopes().
01613 { PROFILE(FUNIT_IS_ONE_SIGNAL_ASSIGNED); 01614 01615 sig_link* sigl = funit->sig_head; 01616 01617 while( (sigl != NULL) && ((sigl->sig->exp_head == NULL) || !SIGNAL_ASSIGN_FROM_DUMPFILE( sigl->sig )) ) { 01618 sigl = sigl->next; 01619 } 01620 01621 PROFILE_END; 01622 01623 return( sigl != NULL ); 01624 01625 }
Returns TRUE if the given functional unit does not contain any input, output or inout ports.
funit | Pointer to functional unit to check |
References FALSE, FUNIT_MODULE, sig_link_s::next, ssuppl_u::part, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, SSUPPL_TYPE_INOUT_NET, SSUPPL_TYPE_INOUT_REG, SSUPPL_TYPE_INPUT_NET, SSUPPL_TYPE_INPUT_REG, SSUPPL_TYPE_OUTPUT_NET, SSUPPL_TYPE_OUTPUT_REG, vsignal_s::suppl, ssuppl_u::type, and func_unit_s::type.
Referenced by db_check_for_top_module().
01265 { PROFILE(FUNIT_IS_TOP_MODULE); 01266 01267 bool retval = FALSE; /* Return value for this function */ 01268 sig_link* sigl; /* Pointer to current signal link */ 01269 01270 assert( funit != NULL ); 01271 01272 /* Only check the signal list if we are a MODULE type */ 01273 if( funit->type == FUNIT_MODULE ) { 01274 01275 sigl = funit->sig_head; 01276 while( (sigl != NULL) && 01277 (sigl->sig->suppl.part.type != SSUPPL_TYPE_INPUT_NET) && 01278 (sigl->sig->suppl.part.type != SSUPPL_TYPE_INPUT_REG) && 01279 (sigl->sig->suppl.part.type != SSUPPL_TYPE_OUTPUT_NET) && 01280 (sigl->sig->suppl.part.type != SSUPPL_TYPE_OUTPUT_REG) && 01281 (sigl->sig->suppl.part.type != SSUPPL_TYPE_INOUT_NET) && 01282 (sigl->sig->suppl.part.type != SSUPPL_TYPE_INOUT_REG) ) { 01283 sigl = sigl->next; 01284 } 01285 01286 retval = (sigl == NULL); 01287 01288 } 01289 01290 PROFILE_END; 01291 01292 return( retval ); 01293 01294 }
Returns TRUE if the given functional unit is an unnamed scope.
funit | Pointer to functional unit to check. |
A functional unit is considered to be an unnamed scope if it is of type FUNIT_NAMED_BLOCK and the last portion of its functional unit name returns TRUE after calling the db_is_unnamed_scope() function.
References db_is_unnamed_scope(), FALSE, FUNIT_ANAMED_BLOCK, FUNIT_NAMED_BLOCK, func_unit_s::name, PROFILE, PROFILE_END, scope_extract_back(), and func_unit_s::type.
Referenced by assertion_funit_summary(), assertion_funit_verbose(), assertion_instance_summary(), assertion_instance_verbose(), combination_funit_summary(), combination_funit_verbose(), combination_get_stats(), combination_instance_summary(), combination_instance_verbose(), combination_reset_counted_exprs(), fsm_funit_summary(), fsm_funit_verbose(), fsm_instance_summary(), fsm_instance_verbose(), func_iter_add_sig_links(), func_iter_add_stmt_links(), func_iter_count_scopes(), funit_is_unnamed_child_of(), instance_find_scope(), line_funit_summary(), line_funit_verbose(), line_get_stats(), line_instance_summary(), line_instance_verbose(), memory_ae_funit_summary(), memory_ae_instance_summary(), memory_funit_verbose(), memory_get_stats(), memory_instance_verbose(), memory_toggle_funit_summary(), memory_toggle_instance_summary(), rank_gather_comp_cdd_cov(), toggle_funit_summary(), toggle_funit_verbose(), toggle_get_stats(), toggle_instance_summary(), and toggle_instance_verbose().
01306 { PROFILE(FUNIT_IS_UNNAMED); 01307 01308 bool retval = FALSE; /* Return value for this function */ 01309 char back[256]; /* Last portion of functional unit name */ 01310 char rest[4096]; /* Rest of functional unit name */ 01311 01312 /* Only begin..end blocks can be unnamed scopes */ 01313 if( (funit->type == FUNIT_NAMED_BLOCK) || (funit->type == FUNIT_ANAMED_BLOCK) ) { 01314 scope_extract_back( funit->name, back, rest ); 01315 retval = db_is_unnamed_scope( back ); 01316 } 01317 01318 PROFILE_END; 01319 01320 return( retval ); 01321 01322 }
Returns TRUE if the specified "parent" functional unit is a parent of the "child" functional unit.
parent | Potential parent functional unit to check for relationship to child | |
child | Potential child functional unit to check for relationship to parent |
References funit_is_unnamed(), func_unit_s::parent, PROFILE, and PROFILE_END.
01330 { PROFILE(FUNIT_IS_UNNAMED_CHILD_OF); 01331 01332 while( (child->parent != NULL) && (child->parent != parent) && funit_is_unnamed( child->parent ) ) { 01333 child = child->parent; 01334 } 01335 01336 PROFILE_END; 01337 01338 return( child->parent == parent ); 01339 01340 }
Merges two functional units into the base functional unit.
Merges two functional units into the base functional unit. Used for creating merged results for GUI usage.
base | Base functional unit that will contain the merged results | |
other | Other functional unit that will be merged |
References func_unit_s::er_head, exclude_merge(), exp_link_s::exp, func_unit_s::exp_head, expression_merge(), func_unit_s::fsm_head, fsm_merge(), func_unit_s::name, exclude_reason_s::next, fsm_link_s::next, sig_link_s::next, exp_link_s::next, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, fsm_link_s::table, and vsignal_merge().
Referenced by instance_merge_tree().
01144 { PROFILE(FUNIT_MERGE); 01145 01146 exp_link* curr_base_exp; /* Pointer to current expression in base functional unit expression list */ 01147 exp_link* curr_other_exp; /* Pointer to current expression in other functional unit expression list */ 01148 sig_link* curr_base_sig; /* Pointer to current signal in base functional unit signal list */ 01149 sig_link* curr_other_sig; /* Pointer to current signal in other functional unit signal list */ 01150 fsm_link* curr_base_fsm; /* Pointer to current FSM in base functional unit FSM list */ 01151 fsm_link* curr_other_fsm; /* Pointer to current FSM in other functional unit FSM list */ 01152 exclude_reason* curr_other_er; 01153 01154 assert( base != NULL ); 01155 assert( base->name != NULL ); 01156 01157 /* Handle all functional unit expressions */ 01158 curr_base_exp = base->exp_head; 01159 curr_other_exp = other->exp_head; 01160 while( (curr_base_exp != NULL) && (curr_other_exp != NULL) ) { 01161 expression_merge( curr_base_exp->exp, curr_other_exp->exp ); 01162 curr_base_exp = curr_base_exp->next; 01163 curr_other_exp = curr_other_exp->next; 01164 } 01165 assert( (curr_base_exp == NULL) && (curr_other_exp == NULL) ); 01166 01167 /* Handle all functional unit signals */ 01168 curr_base_sig = base->sig_head; 01169 curr_other_sig = other->sig_head; 01170 while( (curr_base_sig != NULL) && (curr_other_sig != NULL) ) { 01171 vsignal_merge( curr_base_sig->sig, curr_other_sig->sig ); 01172 curr_base_sig = curr_base_sig->next; 01173 curr_other_sig = curr_other_sig->next; 01174 } 01175 assert( (curr_base_sig == NULL) && (curr_other_exp == NULL) ); 01176 01177 /* Handle all functional unit FSMs */ 01178 curr_base_fsm = base->fsm_head; 01179 curr_other_fsm = other->fsm_head; 01180 while( (curr_base_fsm != NULL) && (curr_other_fsm != NULL) ) { 01181 fsm_merge( curr_base_fsm->table, curr_other_fsm->table ); 01182 curr_base_fsm = curr_base_fsm->next; 01183 curr_other_fsm = curr_other_fsm->next; 01184 } 01185 assert( (curr_base_fsm == NULL) && (curr_other_fsm == NULL) ); 01186 01187 /* Handle all functional unit exclusion reasons */ 01188 curr_other_er = other->er_head; 01189 while( curr_other_er != NULL ) { 01190 exclude_merge( base, curr_other_er ); 01191 curr_other_er = curr_other_er->next; 01192 } 01193 01194 PROFILE_END; 01195 01196 }
void funit_output_dumpvars | ( | FILE * | vfile, | |
func_unit * | funit, | |||
const char * | scope | |||
) |
Outputs dumpvars calls to the given file.
Outputs all of the needed signals to the specified file.
vfile | Pointer to file to output dumpvars information to | |
funit | Pointer to functional unit to output | |
scope | Instance scope |
References ssuppl_u::assigned, FALSE, vsignal_s::name, sig_link_s::next, ssuppl_u::part, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, SSUPPL_TYPE_ENUM, SSUPPL_TYPE_EVENT, SSUPPL_TYPE_GENVAR, SSUPPL_TYPE_MEM, SSUPPL_TYPE_PARAM, SSUPPL_TYPE_PARAM_REAL, vsignal_s::suppl, TRUE, and ssuppl_u::type.
Referenced by instance_output_dumpvars().
01577 { PROFILE(FUNIT_OUTPUT_DUMPVARS); 01578 01579 sig_link* sigl = funit->sig_head; 01580 bool first = TRUE; 01581 01582 while( sigl != NULL ) { 01583 if( (sigl->sig->suppl.part.assigned == 0) && 01584 (sigl->sig->suppl.part.type != SSUPPL_TYPE_PARAM) && 01585 (sigl->sig->suppl.part.type != SSUPPL_TYPE_PARAM_REAL) && 01586 (sigl->sig->suppl.part.type != SSUPPL_TYPE_ENUM) && 01587 (sigl->sig->suppl.part.type != SSUPPL_TYPE_MEM) && 01588 (sigl->sig->suppl.part.type != SSUPPL_TYPE_GENVAR) && 01589 (sigl->sig->suppl.part.type != SSUPPL_TYPE_EVENT) ) { 01590 if( first ) { 01591 first = FALSE; 01592 fprintf( vfile, " $dumpvars( 1, %s.%s", scope, sigl->sig->name ); 01593 } else { 01594 fprintf( vfile, ",\n %s.%s", scope, sigl->sig->name ); 01595 } 01596 } 01597 sigl = sigl->next; 01598 } 01599 01600 if( !first ) { 01601 fprintf( vfile, " );\n" ); 01602 } 01603 01604 PROFILE_END; 01605 01606 }
Pushes the threads associated with the given functional unit onto the active simulation queue.
Adds all of the given functional unit threads to the active simulation queue.
funit | Pointer of functional unit to push threads from | |
stmt | Pointer to the statement to search for in functional unit threads | |
time | Pointer to current simulation time |
References thread_s::curr, func_unit_s::elem, func_unit_s::elem_type, thr_list_s::head, thr_link_s::next, thread_s::part, PROFILE, PROFILE_END, sim_thread_push(), thread_s::suppl, thr_link_s::thr, func_unit_s::thr, THR_ST_WAITING, and func_unit_s::tlist.
Referenced by sim_expr_changed().
01489 { PROFILE(FUNIT_PUSH_THREADS); 01490 01491 assert( funit != NULL ); 01492 01493 if( funit->elem_type == 0 ) { 01494 if( (funit->elem.thr != NULL) && (funit->elem.thr->suppl.part.state == THR_ST_WAITING) && (funit->elem.thr->curr == stmt) ) { 01495 sim_thread_push( funit->elem.thr, time ); 01496 } 01497 } else { 01498 thr_link* curr = funit->elem.tlist->head; 01499 while( (curr != NULL) && (curr->thr != NULL) ) { 01500 if( (curr->thr != NULL) && (curr->thr->suppl.part.state == THR_ST_WAITING) && (curr->thr->curr == stmt) ) { 01501 sim_thread_push( curr->thr, time ); 01502 } 01503 curr = curr->next; 01504 } 01505 } 01506 01507 PROFILE_END; 01508 01509 }
Finds all expressions that call the given statement.
Searches all statement blocks in the given functional unit that have expressions that call the functional unit containing the given statement as its first statement.
funit | Pointer to functional unit to search in | |
stmt | Pointer to statement to search for |
References stmt_link_s::next, statement_s::part, PROFILE, PROFILE_END, statement_contains_expr_calling_stmt(), stmt_link_s::stmt, stmt_blk_add_to_remove_list(), func_unit_s::stmt_head, and statement_s::suppl.
Referenced by instance_remove_stmt_blks_calling_stmt().
00327 { PROFILE(FUNIT_REMOVE_STMT_BLKS_CALLING_STMT); 00328 00329 if( funit != NULL ) { 00330 00331 stmt_link* curr = funit->stmt_head; 00332 00333 /* Search all of the statement blocks */ 00334 while( curr != NULL ) { 00335 if( (curr->stmt->suppl.part.head == 1) && statement_contains_expr_calling_stmt( curr->stmt, stmt ) ) { 00336 stmt_blk_add_to_remove_list( curr->stmt ); 00337 } 00338 curr = curr->next; 00339 } 00340 00341 } 00342 00343 PROFILE_END; 00344 00345 }
void funit_size_elements | ( | func_unit * | funit, | |
funit_inst * | inst, | |||
bool | gen_all, | |||
bool | alloc_exprs | |||
) |
Sizes all elements for the current functional unit from the given instance.
anonymous | expression_resize enumerate_resolve param_resolve expression_set_value expression_set_value expression_set_value vsignal_create_vec gen_item_resize_stmts_and_sigs |
Resizes signals if they are contigent upon parameter values. After all signals have been resized, the signal's corresponding expressions are resized. This function should be called just prior to outputting this funtional unit's contents to the CDD file (after parsing phase only)
funit | Pointer to functional unit containing elements to resize | |
inst | Pointer to instance containing this functional unit | |
gen_all | Set to TRUE to generate all components (this should only be set by the funit_db_write function) | |
alloc_exprs | Allocates vector data for all expressions if set to TRUE |
References enumerate_resolve(), ESUPPL_IS_ROOT, exp_link_s::exp, func_unit_s::exp_head, mod_parm_s::exp_head, vsignal_s::exp_head, EXP_OP_FUNC_CALL, EXP_OP_PASSIGN, expression_resize(), expression_set_value(), FALSE, fsm_create_tables(), func_unit_s::fsm_head, esuppl_u::gen_expr, gen_item_bind(), gen_item_resize_stmts_and_sigs(), gitem_link_s::gi, funit_inst_s::gitem_head, inst_parm_bind(), inst_parm_s::mparm, fsm_link_s::next, sig_link_s::next, gitem_link_s::next, inst_parm_s::next, exp_link_s::next, expression_s::op, funit_inst_s::param_head, param_resolve(), param_set_sig_size(), esuppl_u::part, PROFILE, PROFILE_END, expression_s::sig, sig_link_s::sig, mod_parm_s::sig, inst_parm_s::sig, func_unit_s::sig_head, expression_s::suppl, fsm_link_s::table, TRUE, vector_s::ul, vector_s::value, expression_s::value, and vsignal_create_vec().
Referenced by expression_resize(), funit_db_write(), param_size_function(), and race_check_modules().
00385 { PROFILE(FUNIT_SIZE_ELEMENTS); 00386 00387 inst_parm* curr_iparm; /* Pointer to current instance parameter to evaluate */ 00388 exp_link* curr_exp; /* Pointer to current expression link to evaluate */ 00389 fsm_link* curr_fsm; /* Pointer to current FSM structure to evaluate */ 00390 #ifndef VPI_ONLY 00391 gitem_link* curr_gi; /* Pointer to current generate item link to evaluate */ 00392 #endif 00393 sig_link* curr_sig; /* Pointer to current signal link to evaluate */ 00394 bool resolve = FALSE; /* If set to TRUE, perform one more parameter resolution */ 00395 00396 assert( funit != NULL ); 00397 assert( inst != NULL ); 00398 00399 /* 00400 First, traverse through current instance's parameter list and resolve 00401 any unresolved parameters created via generate statements. 00402 */ 00403 curr_iparm = inst->param_head; 00404 while( curr_iparm != NULL ) { 00405 if( curr_iparm->mparm == NULL ) { 00406 curr_exp = curr_iparm->sig->exp_head; 00407 while( curr_exp != NULL ) { 00408 if( curr_exp->exp->suppl.part.gen_expr == 0 ) { 00409 expression_set_value( curr_exp->exp, curr_iparm->sig, funit ); 00410 resolve = TRUE; 00411 } 00412 curr_exp = curr_exp->next; 00413 } 00414 } 00415 curr_iparm = curr_iparm->next; 00416 } 00417 00418 /* If we need to do another parameter resolution for generate blocks, do it now */ 00419 if( resolve ) { 00420 param_resolve( inst ); 00421 } 00422 00423 #ifndef VPI_ONLY 00424 /* 00425 Second, traverse through any BIND generate items and update the expression name. 00426 */ 00427 curr_gi = inst->gitem_head; 00428 while( curr_gi != NULL ) { 00429 gen_item_bind( curr_gi->gi ); 00430 curr_gi = curr_gi->next; 00431 } 00432 #endif 00433 00434 /* 00435 Third, traverse through current instance's instance parameter list and 00436 set sizes of signals and expressions. 00437 */ 00438 curr_iparm = inst->param_head; 00439 while( curr_iparm != NULL ) { 00440 inst_parm_bind( curr_iparm ); 00441 if( curr_iparm->mparm != NULL ) { 00442 /* This parameter sizes a signal so perform the signal size */ 00443 if( curr_iparm->mparm->sig != NULL ) { 00444 param_set_sig_size( curr_iparm->mparm->sig, curr_iparm ); 00445 } else { 00446 /* This parameter attaches to an expression tree */ 00447 curr_exp = curr_iparm->mparm->exp_head; 00448 while( curr_exp != NULL ) { 00449 expression_set_value( curr_exp->exp, curr_iparm->sig, funit ); 00450 curr_exp = curr_exp->next; 00451 } 00452 } 00453 } 00454 curr_iparm = curr_iparm->next; 00455 } 00456 00457 /* Traverse through all signals, calculating and creating their vector values */ 00458 curr_sig = funit->sig_head; 00459 while( curr_sig != NULL ) { 00460 vsignal_create_vec( curr_sig->sig ); 00461 curr_sig = curr_sig->next; 00462 } 00463 00464 /* 00465 Fourth, resolve all enumerated values for this functional unit 00466 */ 00467 enumerate_resolve( inst ); 00468 00469 /* 00470 Fifth, traverse all expressions and set expressions to specified 00471 signals. Makes the assumption that all children expressions come 00472 before the root expression in the list (this is currently the case). 00473 */ 00474 curr_exp = funit->exp_head; 00475 while( curr_exp != NULL ) { 00476 if( ESUPPL_IS_ROOT( curr_exp->exp->suppl ) ) { 00477 /* Perform an entire expression resize */ 00478 expression_resize( curr_exp->exp, funit, TRUE, alloc_exprs ); 00479 } 00480 if( (curr_exp->exp->sig != NULL) && 00481 (curr_exp->exp->op != EXP_OP_FUNC_CALL) && 00482 (curr_exp->exp->op != EXP_OP_PASSIGN) ) { 00483 expression_set_value( curr_exp->exp, curr_exp->exp->sig, funit ); 00484 assert( curr_exp->exp->value->value.ul != NULL ); 00485 } 00486 curr_exp = curr_exp->next; 00487 } 00488 00489 #ifndef VPI_ONLY 00490 /* Sixth, traverse all generate items and resize all expressions and signals. */ 00491 curr_gi = inst->gitem_head; 00492 while( curr_gi != NULL ) { 00493 gen_item_resize_stmts_and_sigs( curr_gi->gi, funit ); 00494 curr_gi = curr_gi->next; 00495 } 00496 #endif 00497 00498 if( gen_all ) { 00499 00500 /* 00501 Last, size all FSMs. Since the FSM structure is reliant on the size 00502 of the state variable signal to which it is attached, its tables 00503 cannot be created until the state variable size can be calculated. 00504 Since this has been done now, size the FSMs. 00505 */ 00506 curr_fsm = funit->fsm_head; 00507 while( curr_fsm != NULL ) { 00508 fsm_create_tables( curr_fsm->table ); 00509 curr_fsm = curr_fsm->next; 00510 } 00511 00512 } 00513 00514 PROFILE_END; 00515 00516 }
void funit_version_db_read | ( | func_unit * | funit, | |
char ** | line | |||
) |
Reads the functional unit version information from the functional unit line and adds it to the current functional unit.
Reads in the functional unit version information from the specified CDD line.
funit | Pointer to current functional unit to read version into | |
line | Pointer to current line to parse |
References PROFILE, PROFILE_END, strdup_safe, and func_unit_s::version.
Referenced by db_read().
00749 { PROFILE(FUNIT_VERSION_DB_READ); 00750 00751 /* The current functional unit version must not have already been set */ 00752 assert( funit->version == NULL ); 00753 00754 /* Strip the leading whitespace */ 00755 while( **line == ' ' ) (*line)++; 00756 00757 /* The rest of the line will be the version information (internal whitespace is allowed) */ 00758 funit->version = strdup_safe( *line ); 00759 00760 PROFILE_END; 00761 00762 }