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

/Users/trevorw/projects/release/covered-0.7.4/src/db.h File Reference


Detailed Description

Contains functions for writing and reading contents of covered database file.

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
12/7/2001

#include "defines.h"

Go to the source code of this file.

Functions

dbdb_create ()
 Creates a new database.

void db_close ()
 Deallocates all memory consumed by the database.

bool db_check_for_top_module ()
 Checks to see if the module specified by the -t option is the top-level module of the simulator.

void db_write (const char *file, bool parse_mode, bool issue_ids, bool report_save)
 Writes contents of expressions, functional units and vsignals to database file.

void db_read (const char *file, int read_mode)
 Reads contents of database file and stores into internal lists.

void db_merge_instance_trees ()
 Merges the current instance trees.

uint64 db_scale_to_precision (uint64 value, func_unit *funit)
 Returns a scaled version of the given value to the timescale for the given functional unit.

void db_set_timescale (int unit, int precision)
 Sets the global timescale unit and precision variables.

func_unitdb_get_curr_funit ()
 Returns a pointer to the current functional unit.

unsigned int db_get_exclusion_id_size ()
 Calculates and returns the size of the exclusion ID string.

char * db_gen_exclusion_id (char type, int id)
 Allocates memory for and generates the exclusion identifier.

char * db_create_unnamed_scope ()
 Creates a scope name for an unnamed scope. Called only during parsing.

bool db_is_unnamed_scope (char *scope)
 Returns TRUE if the given scope is an unnamed scope name; otherwise, returns FALSE.

void db_add_file_version (const char *file, const char *version)
 Adds the given filename and version information to the database.

void db_output_dumpvars (FILE *vfile)
 Outputs all needed signals in $dumpvars calls to the specified file.

func_unitdb_add_instance (char *scope, char *name, int type, vector_width *range)
 Adds specified functional unit node to functional unit tree. Called by parser.

void db_add_module (char *name, char *file, int start_line)
 Adds specified module to module list. Called by parser.

bool db_add_function_task_namedblock (int type, char *name, char *file, int start_line)
 Adds specified task/function to functional unit list. Called by parser.

void db_end_function_task_namedblock (int end_line)
 Performs actions necessary when the end of a function/task/named-block is seen. Called by parser.

void db_add_declared_param (bool is_signed, static_expr *msb, static_expr *lsb, char *name, expression *expr, bool local)
 Adds specified declared parameter to parameter list. Called by parser.

void db_add_override_param (char *inst_name, expression *expr, char *param_name)
 Adds specified override parameter to parameter list. Called by parser.

void db_add_defparam (char *name, expression *expr)
 Adds specified defparam to parameter override list. Called by parser.

void db_add_signal (char *name, int type, sig_range *prange, sig_range *urange, bool is_signed, bool mba, int line, int col, bool handled)
 Adds specified vsignal to vsignal list. Called by parser.

statementdb_add_fork_join (statement *stmt)
 Creates statement block that acts like a fork join block from a standard statement block.

void db_add_enum (vsignal *enum_sig, static_expr *value)
 Creates an enumerated list based on the given parameters.

void db_end_enum_list ()
 Called after all enumerated values for the current list have been added.

void db_add_typedef (const char *name, bool is_signed, bool is_handled, bool is_sizable, sig_range *prange, sig_range *urange)
 Adds given typedefs to the database.

void db_end_module (int end_line)
 Called when the endmodule keyword is parsed.

void db_end_function_task (int end_line)
 Called when the endfunction or endtask keyword is parsed.

vsignaldb_find_signal (char *name, bool okay_if_not_found)
 Finds specified signal in functional unit and returns pointer to the signal structure. Called by parser.

void db_add_gen_item_block (gen_item *gi)
 Adds a generate block to the database. Called by parser.

gen_itemdb_find_gen_item (gen_item *root, gen_item *gi)
 Find specified generate item in the current functional unit. Called by parser.

typedef_itemdb_find_typedef (const char *name)
 Finds specified typedef and returns TRUE if it is found.

gen_itemdb_get_curr_gen_block ()
 Returns a pointer to the current implicitly connected generate block. Called by parser.

expressiondb_create_expression (expression *right, expression *left, exp_op_type op, bool lhs, int line, int first, int last, char *sig_name)
 Creates new expression from specified information. Called by parser and db_add_expression.

void db_bind_expr_tree (expression *root, char *sig_name)
 Binds all necessary sub-expressions in the given tree to the given signal name.

expressiondb_create_expr_from_static (static_expr *se, int line, int first_col, int last_col)
 Creates an expression from the specified static expression.

void db_add_expression (expression *root)
 Adds specified expression to expression list. Called by parser.

expressiondb_create_sensitivity_list (statement *stmt)
 Creates an expression tree sensitivity list for the given statement block.

statementdb_parallelize_statement (statement *stmt)
 Checks specified statement for parallelization and if it must be, creates a parallel statement block.

statementdb_create_statement (expression *exp, unsigned int ppline)
 Creates new statement expression from specified information. Called by parser.

void db_add_statement (statement *stmt, statement *start)
 Adds specified statement to current functional unit's statement list. Called by parser.

void db_remove_statement_from_current_funit (statement *stmt)
 Removes specified statement from current functional unit.

void db_remove_statement (statement *stmt)
 Removes specified statement and associated expression from list and memory.

void db_gen_item_connect_true (gen_item *gi1, gen_item *gi2)
 Connects gi2 to the true path of gi1.

void db_gen_item_connect_false (gen_item *gi1, gen_item *gi2)
 Connects gi2 to the false path of gi1.

void db_gen_item_connect (gen_item *gi1, gen_item *gi2)
 Connects one generate item block to another.

bool db_statement_connect (statement *curr_stmt, statement *next_stmt)
 Connects one statement block to another.

void db_connect_statement_true (statement *stmt, statement *exp_true)
 Connects true statement to specified statement.

void db_connect_statement_false (statement *stmt, statement *exp_false)
 Connects false statement to specified statement.

attr_paramdb_create_attr_param (char *name, expression *expr)
 Allocates and initializes an attribute parameter.

void db_parse_attribute (attr_param *ap)
 Parses the specified attribute parameter list for Covered attributes.

void db_remove_stmt_blks_calling_statement (statement *stmt)
 Searches entire design for expressions that call the specified statement.

void db_sync_curr_instance ()
 Synchronizes the curr_instance pointer to match the curr_inst_scope hierarchy.

void db_set_vcd_scope (const char *scope)
 Sets current VCD scope to specified scope.

void db_vcd_upscope ()
 Moves current VCD hierarchy up one level.

void db_assign_symbol (const char *name, const char *symbol, int msb, int lsb)
 Adds symbol to signal specified by name.

void db_set_symbol_char (const char *sym, char value)
 Sets the found symbol value to specified character value. Called by VCD lexer.

void db_set_symbol_string (const char *sym, const char *value)
 Sets the found symbol value to specified string value. Called by VCD lexer.

bool db_do_timestep (uint64 time, bool final)
 Performs a timestep for all signal changes during this timestep.


Function Documentation

void db_add_declared_param bool  is_signed,
static_expr msb,
static_expr lsb,
char *  name,
expression expr,
bool  local
 

Adds specified declared parameter to parameter list. Called by parser.

Searches current module to verify that specified parameter name has not been previously used in the module. If the parameter name has not been found, it is created added to the current module's parameter list.

Parameters:
is_signed  Specified if the declared parameter needs to be handled as a signed value
msb  Static expression containing MSB of this declared parameter
lsb  Static expression containing LSB of this declared parameter
name  Name of declared parameter to add
expr  Expression containing value of this parameter
local  If TRUE, specifies that this parameter is a local parameter

01305   { PROFILE(DB_ADD_DECLARED_PARAM);
01306 
01307   mod_parm* mparm;  /* Pointer to added module parameter */
01308 
01309   assert( name != NULL );
01310 
01311   /* If a parameter value type is not supported, don't create this parameter */
01312   if( expr != NULL ) {
01313 
01314 #ifdef DEBUG_MODE
01315     if( debug_mode ) {
01316       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_declared_param, param: %s, expr: %d, local: %d", obf_sig( name ), expr->id, local );
01317       assert( rv < USER_MSG_LENGTH );
01318       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01319     }
01320 #endif
01321 
01322     if( mod_parm_find( name, curr_funit->param_head ) == NULL ) {
01323 
01324       /* Add parameter to module parameter list */
01325       mparm = mod_parm_add( name, msb, lsb, is_signed, expr, (local ? PARAM_TYPE_DECLARED_LOCAL : PARAM_TYPE_DECLARED), curr_funit, NULL );
01326 
01327     }
01328 
01329   }
01330 
01331   PROFILE_END;
01332 
01333 }

void db_add_defparam char *  name,
expression expr
 

Adds specified defparam to parameter override list. Called by parser.

Adds specified parameter to the defparam list.

Parameters:
name  Name of parameter value to override
expr  Expression value of parameter override

01411   { PROFILE(DB_ADD_DEFPARAM);
01412 
01413 #ifdef DEBUG_MODE
01414   if( debug_mode ) {
01415     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_defparam, defparam: %s", obf_sig( name ) );
01416     assert( rv < USER_MSG_LENGTH );
01417     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01418   }
01419 #endif
01420 
01421   {
01422     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "defparam construct is not supported, line: %d.  Use -P option to score instead", expr->line );
01423     assert( rv < USER_MSG_LENGTH );
01424     print_output( user_msg, WARNING, __FILE__, __LINE__ );
01425   }
01426 
01427   expression_dealloc( expr, FALSE );
01428 
01429   PROFILE_END;
01430 
01431 }

void db_add_enum vsignal enum_sig,
static_expr value
 

Creates an enumerated list based on the given parameters.

Allocates and adds an enum_item to the current module's list to be elaborated later.

Parameters:
enum_sig  Pointer to signal created for the given enumerated value
value  Value to later assign to the enum_sig (during elaboration)

01589   { PROFILE(DB_ADD_ENUM);
01590 
01591   assert( enum_sig != NULL );
01592 
01593 #ifdef DEBUG_MODE
01594   if( debug_mode ) {
01595     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_enum, sig_name: %s", enum_sig->name );
01596     assert( rv < USER_MSG_LENGTH );
01597     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01598   }
01599 #endif
01600 
01601   enumerate_add_item( enum_sig, value, curr_funit );
01602 
01603   PROFILE_END;
01604 
01605 }

void db_add_expression expression root  ) 
 

Adds specified expression to expression list. Called by parser.

Adds the specified expression to the current module's expression list.

Parameters:
root  Pointer to root expression to add to module expression list

02121   { PROFILE(DB_ADD_EXPRESSION);
02122 
02123   if( (root != NULL) && (root->suppl.part.exp_added == 0) ) {
02124 
02125 #ifdef DEBUG_MODE
02126     if( debug_mode ) {
02127       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_expression, id: %d, op: %s, line: %d", 
02128                                   root->id, expression_string_op( root->op ), root->line );
02129       assert( rv < USER_MSG_LENGTH );
02130       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02131     }
02132 #endif
02133 
02134     if( generate_top_mode > 0 ) {
02135 
02136       if( root->suppl.part.gen_expr == 1 ) {
02137 
02138         /* Add root expression to the generate item list for the current functional unit */
02139         last_gi = gen_item_create_expr( root );
02140 
02141         /* Attach it to the curr_gi_block, if one exists */
02142         if( curr_gi_block != NULL ) {
02143           db_gen_item_connect( curr_gi_block, last_gi );
02144         } else {
02145           curr_gi_block = last_gi;
02146         }
02147 
02148       }
02149 
02150     } else {
02151 
02152       /* Add expression's children first. */
02153       db_add_expression( root->right );
02154       db_add_expression( root->left );
02155 
02156       /* Now add this expression to the list. */
02157       exp_link_add( root, &(curr_funit->exp_head), &(curr_funit->exp_tail) );
02158 
02159     }
02160 
02161     /* Specify that this expression has already been added */
02162     root->suppl.part.exp_added = 1;
02163 
02164   }
02165 
02166   PROFILE_END;
02167 
02168 }

void db_add_file_version const char *  file,
const char *  version
 

Adds the given filename and version information to the database.

Adds the given filename and version information to the database.

Parameters:
file  Name of file to set version information to
version  Name of file version

00952   { PROFILE(DB_ADD_FILE_VERSION);
00953 
00954   str_link* strl;
00955 
00956 #ifdef DEBUG_MODE
00957   if( debug_mode ) {
00958     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_file_version, file: %s, version: %s", obf_file( file ), version );
00959     assert( rv < USER_MSG_LENGTH );
00960     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00961   }
00962 #endif
00963 
00964   /* Add the new file version information */
00965   strl       = str_link_add( strdup_safe( file ), &(db_list[curr_db]->fver_head), &(db_list[curr_db]->fver_tail) );
00966   strl->str2 = strdup_safe( version );
00967 
00968   PROFILE_END;
00969 
00970 }

statement* db_add_fork_join statement stmt  ) 
 

Creates statement block that acts like a fork join block from a standard statement block.

bool db_add_function_task_namedblock int  type,
char *  name,
char *  file,
int  start_line
 

Adds specified task/function to functional unit list. Called by parser.

Returns:
Returns TRUE if the new functional unit was added to the design; otherwise, returns FALSE to indicate that this block should be ignored.
Exceptions:
anonymous Throw
Creates a new function, task or named block scope and adds it to the instance tree. Also sets the curr_funit global pointer to point to this new functional unit.
Parameters:
type  Specifies type of functional unit being added (function, task or named_block)
name  Name of functional unit
file  File containing the specified functional unit
start_line  Starting line number of functional unit

01182   { PROFILE(DB_ADD_FUNCTION_TASK_NAMEDBLOCK);
01183 
01184   func_unit* tf = NULL;  /* Pointer to created functional unit */
01185   func_unit* parent;     /* Pointer to parent module for the newly created functional unit */
01186   char*      full_name;  /* Full name of function/task/namedblock which includes the parent module name */
01187 
01188   assert( (type == FUNIT_FUNCTION)  || (type == FUNIT_TASK) || (type == FUNIT_NAMED_BLOCK) ||
01189           (type == FUNIT_AFUNCTION) || (type == FUNIT_ATASK) );
01190 
01191 #ifdef DEBUG_MODE
01192   if( debug_mode ) {
01193     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_function_task_namedblock, %s: %s, file: %s, start_line: %d",
01194                                 get_funit_type( type ), obf_funit( name ), obf_file( file ), start_line );
01195     assert( rv < USER_MSG_LENGTH );
01196     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01197   }
01198 #endif
01199 
01200   /* Generate full name to use for the function/task */
01201   full_name = funit_gen_task_function_namedblock_name( name, curr_funit );
01202 
01203   Try {
01204 
01205     /* Add this as an instance so we can get scope */
01206     if( (tf = db_add_instance( name, full_name, type, NULL )) != NULL ) {
01207 
01208       /* Get parent */
01209       parent = funit_get_curr_module( curr_funit );
01210 
01211       if( generate_expr_mode > 0 ) {
01212         /* Change the recently created instance generate item to a TFN item */
01213         last_gi->suppl.part.type = GI_TYPE_TFN;
01214       } else {
01215         /* Store this functional unit in the parent module list */
01216         funit_link_add( tf, &(parent->tf_head), &(parent->tf_tail) );
01217       }
01218 
01219       /* Set our parent pointer to the current functional unit */
01220       tf->parent = curr_funit;
01221 
01222       /* If we are in an automatic task or function, set our type to FUNIT_ANAMED_BLOCK */
01223       if( (curr_funit->type == FUNIT_AFUNCTION) ||
01224           (curr_funit->type == FUNIT_ATASK) ||
01225           (curr_funit->type == FUNIT_ANAMED_BLOCK) ) {
01226         assert( tf->type == FUNIT_NAMED_BLOCK );
01227         tf->type = FUNIT_ANAMED_BLOCK;
01228       }
01229 
01230       /* Set current functional unit to this functional unit */
01231       curr_funit             = tf;
01232       curr_funit->filename   = strdup_safe( file );
01233       curr_funit->start_line = start_line;
01234       curr_funit->ts_unit    = current_timescale_unit;
01235     
01236     }
01237 
01238   } Catch_anonymous {
01239     free_safe( full_name, (strlen( full_name ) + 1) );
01240     Throw 0;
01241   }
01242 
01243   free_safe( full_name, (strlen( full_name ) + 1) );
01244 
01245   PROFILE_END;
01246 
01247   return( tf != NULL );
01248 
01249 }

void db_add_gen_item_block gen_item gi  ) 
 

Adds a generate block to the database. Called by parser.

Adds the specified generate item block to the list of generate blocks for the current functional unit.

Parameters:
gi  Pointer to the head of a generate item block to add

01723   { PROFILE(DB_ADD_GEN_ITEM_BLOCK);
01724 
01725   if( gi != NULL ) {
01726 
01727     /* Add the generate block to the list of generate blocks for this functional unit */
01728     gitem_link_add( gi, &(curr_funit->gitem_head), &(curr_funit->gitem_tail) );
01729 
01730   }
01731 
01732   PROFILE_END;
01733 
01734 }

func_unit* db_add_instance char *  scope,
char *  name,
int  type,
vector_width range
 

Adds specified functional unit node to functional unit tree. Called by parser.

Returns:
Returns a pointer to the created functional unit if the instance was added to the hierarchy; otherwise, returns NULL.
Exceptions:
anonymous Throw
Creates a new functional unit node with the instantiation name, search for matching functional unit. If functional unit hasn't been created previously, create it now without a filename associated (NULL). Add functional unit node to tree if there are no problems in doing so.
Parameters:
scope  Name of functional unit instance being added
name  Name of functional unit being instantiated
type  Type of functional unit being instantiated
range  Optional range (used for arrays of instances)

01005   { PROFILE(DB_ADD_INSTANCE);
01006 
01007   func_unit*  funit = NULL;      /* Pointer to functional unit */
01008   funit_link* found_funit_link;  /* Pointer to found funit_link in functional unit list */
01009   bool        score;             /* Specifies if this module should be scored */
01010 
01011   /* There should always be a parent so internal error if it does not exist. */
01012   assert( curr_funit != NULL );
01013 
01014   /* If this functional unit name is in our list of no_score functional units, skip adding the instance */
01015   score = str_link_find( name, no_score_head ) == NULL;
01016 
01017 #ifdef DEBUG_MODE
01018   if( debug_mode ) {
01019     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_instance, instance: %s, %s: %s (curr_funit: %s)",
01020                                 obf_inst( scope ), get_funit_type( type ), obf_funit( name ), obf_funit( curr_funit->name ) );
01021     assert( rv < USER_MSG_LENGTH );
01022     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01023   }
01024 #endif
01025 
01026   /* Create new functional unit node */
01027   funit       = funit_create();
01028   funit->name = strdup_safe( name );
01029   funit->type = score ? type : FUNIT_NO_SCORE;
01030 
01031   /* If a range has been specified, calculate its width and lsb now */
01032   if( (range != NULL) && score ) {
01033     if( (range->left != NULL) && (range->left->exp != NULL) ) {
01034       (void)mod_parm_add( NULL, NULL, NULL, FALSE, range->left->exp, PARAM_TYPE_INST_MSB, curr_funit, scope );
01035     }
01036     if( (range->right != NULL) && (range->right->exp != NULL) ) {
01037       (void)mod_parm_add( NULL, NULL, NULL, FALSE, range->right->exp, PARAM_TYPE_INST_LSB, curr_funit, scope );
01038     }
01039   }
01040 
01041   if( ((found_funit_link = funit_link_find( funit->name, funit->type, db_list[curr_db]->funit_head )) != NULL) && (generate_top_mode == 0) ) {
01042 
01043     if( type != FUNIT_MODULE ) {
01044       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Multiple identical task/function/named-begin-end names (%s) found in module %s, file %s",
01045                                   scope, obf_funit( curr_funit->name ), obf_file( curr_funit->filename ) );
01046       assert( rv < USER_MSG_LENGTH );
01047       print_output( user_msg, FATAL, __FILE__, __LINE__ );
01048       funit_dealloc( funit );
01049       Throw 0;
01050     }
01051 
01052     if( (last_gi == NULL) || (last_gi->suppl.part.type != GI_TYPE_INST) ||
01053         !instance_parse_add( &last_gi->elem.inst, curr_funit, found_funit_link->funit, scope, range, FALSE, TRUE, FALSE, FALSE ) ) {
01054       inst_link* instl = db_list[curr_db]->inst_head;
01055       while( (instl != NULL) && !instance_parse_add( &instl->inst, curr_funit, found_funit_link->funit, scope, range, FALSE, FALSE, FALSE, FALSE ) ) {
01056         instl = instl->next;
01057       }
01058       if( instl == NULL ) {
01059         (void)inst_link_add( instance_create( found_funit_link->funit, scope, FALSE, FALSE, FALSE, range ), &(db_list[curr_db]->inst_head), &(db_list[curr_db]->inst_tail) );
01060       }
01061     }
01062 
01063     funit_dealloc( funit );
01064 
01065   } else {
01066 
01067     /* Add new functional unit to functional unit list. */
01068     funit_link_add( funit, &(db_list[curr_db]->funit_head), &(db_list[curr_db]->funit_tail) );
01069 
01070     /* If we are currently within a generate block, create a generate item for this instance to resolve it later */
01071     if( generate_top_mode > 0 ) {
01072       last_gi = gen_item_create_inst( instance_create( funit, scope, FALSE, FALSE, FALSE, range ) );
01073       if( curr_gi_block != NULL ) {
01074         db_gen_item_connect( curr_gi_block, last_gi );
01075       } else {
01076         curr_gi_block = last_gi;
01077       }
01078     }
01079 
01080     /* Add the instance to the instance tree in the proper place */
01081     {
01082       inst_link* instl = db_list[curr_db]->inst_head;
01083       while( (instl != NULL) && !instance_parse_add( &instl->inst, curr_funit, funit, scope, range, FALSE, FALSE, (generate_top_mode > 0), (generate_expr_mode > 0) ) ) {
01084         instl = instl->next;
01085       }
01086       if( instl == NULL ) {
01087         (void)inst_link_add( instance_create( funit, scope, FALSE, (generate_top_mode > 0), (generate_expr_mode > 0), range ), &(db_list[curr_db]->inst_head), &(db_list[curr_db]->inst_tail) );
01088       }
01089     }
01090 
01091     if( (type == FUNIT_MODULE) && score && (str_link_find( name, modlist_head ) == NULL) ) {
01092       (void)str_link_add( strdup_safe( name ), &modlist_head, &modlist_tail );
01093     }
01094       
01095   }
01096 
01097   PROFILE_END;
01098 
01099   return( score ? funit : NULL );
01100 
01101 }

void db_add_module char *  name,
char *  file,
int  start_line
 

Adds specified module to module list. Called by parser.

Creates a new module element with the contents specified by the parameters given and inserts this module into the module list. This function can only be called when we are actually parsing a module which implies that we must have the name of the module at the head of the modlist linked-list structure.

Parameters:
name  Name of module being added to tree
file  Filename that module is a part of
start_line  Starting line number of this module in the file

01113   { PROFILE(DB_ADD_MODULE);
01114 
01115   funit_link* modl;  /* Pointer to found tree node */
01116 
01117 #ifdef DEBUG_MODE
01118   if( debug_mode ) {
01119     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_module, module: %s, file: %s, start_line: %d",
01120                                 obf_funit( name ), obf_file( file ), start_line );
01121     assert( rv < USER_MSG_LENGTH );
01122     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01123   }
01124 #endif
01125 
01126   modl = funit_link_find( name, FUNIT_MODULE, db_list[curr_db]->funit_head );
01127 
01128   assert( modl != NULL );
01129 
01130   curr_funit             = modl->funit;
01131   curr_funit->filename   = strdup_safe( file );
01132   curr_funit->start_line = start_line;
01133   curr_funit->ts_unit    = current_timescale_unit;
01134 
01135   /* Clear the unnamed scope ID */
01136   unnamed_scope_id = 0;
01137 
01138   PROFILE_END;
01139   
01140 }

void db_add_override_param char *  inst_name,
expression expr,
char *  param_name
 

Adds specified override parameter to parameter list. Called by parser.

Creates override parameter and stores this in the current module as well as all associated instances.

Parameters:
inst_name  Name of instance being overridden
expr  Expression containing value of override parameter
param_name  Name of parameter being overridden (for parameter_value_byname syntax)

01343   { PROFILE(DB_ADD_OVERRIDE_PARAM);
01344 
01345   mod_parm* mparm;  /* Pointer to module parameter added to current module */
01346 
01347 #ifdef DEBUG_MODE
01348   if( debug_mode ) {
01349     unsigned int rv;
01350     if( param_name != NULL ) {
01351       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_override_param, instance: %s, param_name: %s",
01352                      obf_inst( inst_name ), obf_sig( param_name ) );
01353     } else {
01354       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_override_param, instance: %s", obf_inst( inst_name ) );
01355     }
01356     assert( rv < USER_MSG_LENGTH );
01357     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01358   }
01359 #endif
01360 
01361   /* Add override parameter to module parameter list */
01362   mparm = mod_parm_add( param_name, NULL, NULL, FALSE, expr, PARAM_TYPE_OVERRIDE, curr_funit, inst_name );
01363 
01364   PROFILE_END;
01365 
01366 }

void db_add_signal char *  name,
int  type,
sig_range prange,
sig_range urange,
bool  is_signed,
bool  mba,
int  line,
int  col,
bool  handled
 

Adds specified vsignal to vsignal list. Called by parser.

Creates a new signal with the specified parameter information and adds this to the signal list if it does not already exist. If width == 0, the sig_msb and sig_lsb values are interrogated. If sig_msb and/or is non-NULL, its value is add to the current module's parameter list and all associated instances are updated to contain new value.

Parameters:
name  Name of signal being added
type  Type of signal being added
prange  Specifies packed signal range information
urange  Specifies unpacked signal range information
is_signed  Specifies that this signal is signed (TRUE) or not (FALSE)
mba  Set to TRUE if specified signal must be assigned by simulated results
line  Line number where signal was declared
col  Starting column where signal was declared
handled  Specifies if this signal is handled by Covered or not

01450   { PROFILE(DB_ADD_SIGNAL);
01451 
01452   vsignal*     sig = NULL;  /* Container for newly created signal */
01453   sig_link*    sigl;        /* Pointer to found signal link */
01454   unsigned int i;           /* Loop iterator */
01455   int          j   = 0;     /* Loop iterator */
01456 
01457 #ifdef DEBUG_MODE
01458   if( debug_mode ) {
01459     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_signal, signal: %s, type: %d, line: %d, col: %d", obf_sig( name ), type, line, col );
01460     assert( rv < USER_MSG_LENGTH );
01461     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01462   }
01463 #endif
01464 
01465   /* Add signal to current module's signal list if it does not already exist */
01466   if( (sigl = sig_link_find( name, curr_funit->sig_head )) == NULL ) {
01467 
01468     /* Create the signal */
01469     if( (type == SSUPPL_TYPE_GENVAR) || (type == SSUPPL_TYPE_DECL_SREAL) ) {
01470       /* For genvars and shortreals, set the size to 32, automatically */
01471       sig = vsignal_create( name, type, 32, line, col );
01472     } else if( type == SSUPPL_TYPE_DECL_REAL ) {
01473       /* For real types, they should be automatically sized to 64, automatically */
01474       sig = vsignal_create( name, type, 64, line, col );
01475     } else {
01476       /* For normal signals just make the width a value of 1 for now -- it will be resized during funit_resize_elements */
01477       sig = vsignal_create( name, type, 1, line, col );
01478     }
01479 
01480   /* If the signal has currently existed, check to see if the signal is unsized, and, if so, size it now */
01481   } else if( sigl->sig->suppl.part.implicit_size ) {
01482 
01483     sig = sigl->sig;
01484     sig->suppl.part.implicit_size = 0;
01485 
01486   }
01487 
01488   /* Check all of the dimensions within range and create vector parameters, if necessary */
01489   if( sig != NULL ) {
01490     if( sig->dim != NULL ) {
01491       free_safe( sig->dim, (sizeof( dim_range ) * (sig->pdim_num + sig->udim_num)) );
01492     }
01493     assert( prange != NULL );
01494     sig->udim_num = (urange != NULL) ? urange->dim_num : 0;
01495     sig->pdim_num = prange->dim_num;
01496     assert( (sig->pdim_num + sig->udim_num) > 0 );
01497     sig->dim = (dim_range*)malloc_safe( sizeof( dim_range ) * (sig->pdim_num + sig->udim_num) );
01498     for( i=0; i<sig->udim_num; i++ ) {
01499       assert( urange->dim[i].left != NULL );
01500       if( urange->dim[i].left->exp != NULL ) {
01501         db_add_vector_param( sig, urange->dim[i].left->exp, PARAM_TYPE_SIG_MSB, j );
01502       } else {
01503         sig->dim[j].msb = urange->dim[i].left->num;
01504       }
01505       assert( urange->dim[i].right != NULL );
01506       if( urange->dim[i].right->exp != NULL ) {
01507         db_add_vector_param( sig, urange->dim[i].right->exp, PARAM_TYPE_SIG_LSB, j );
01508       } else {
01509         sig->dim[j].lsb = urange->dim[i].right->num;
01510       }
01511       j++;
01512     }
01513     for( i=0; i<sig->pdim_num; i++ ) {
01514       assert( prange->dim[i].left != NULL );
01515       if( prange->dim[i].left->exp != NULL ) {
01516         db_add_vector_param( sig, prange->dim[i].left->exp, PARAM_TYPE_SIG_MSB, j );
01517       } else {
01518         sig->dim[j].msb = prange->dim[i].left->num;
01519       }
01520       assert( prange->dim[i].right != NULL );
01521       if( prange->dim[i].right->exp != NULL ) {
01522         db_add_vector_param( sig, prange->dim[i].right->exp, PARAM_TYPE_SIG_LSB, j );
01523       } else {
01524         sig->dim[j].lsb = prange->dim[i].right->num;
01525       }
01526       j++;
01527     }
01528 
01529     /* If exclude_mode is not zero, set the exclude bit in the signal */
01530     sig->suppl.part.excluded = (exclude_mode > 0) ? 1 : 0;
01531 
01532     /* Specify that we should not deallocate the expressions */
01533     if( prange != NULL ) {
01534       prange->exp_dealloc = FALSE;
01535     }
01536     if( urange != NULL ) {
01537       urange->exp_dealloc = FALSE;
01538     }
01539   }
01540 
01541   /* Only do the following if the signal was not previously found */
01542   if( sigl == NULL ) {
01543 
01544     /* Add the signal to either the functional unit or a generate item */
01545     if( (generate_top_mode > 0) && (type != SSUPPL_TYPE_GENVAR) ) {
01546       last_gi = gen_item_create_sig( sig );
01547       if( curr_gi_block != NULL ) {
01548         db_gen_item_connect( curr_gi_block, last_gi );
01549       } else {
01550         curr_gi_block = last_gi;
01551       }
01552     } else {
01553       /* Add signal to current module's signal list */
01554       sig_link_add( sig, &(curr_funit->sig_head), &(curr_funit->sig_tail) );
01555     }
01556 
01557     /* Indicate if signal must be assigned by simulated results or not */
01558     if( mba ) {
01559       sig->suppl.part.mba      = 1;
01560       sig->suppl.part.assigned = 1;
01561     }
01562 
01563     /* Indicate signed attribute */
01564     sig->value->suppl.part.is_signed = is_signed;
01565 
01566     /* Indicate handled attribute */
01567     sig->suppl.part.not_handled = handled ? 0 : 1;
01568 
01569     /* Set the implicit_size attribute */
01570     sig->suppl.part.implicit_size = (((type == SSUPPL_TYPE_INPUT_NET)  || (type == SSUPPL_TYPE_INPUT_REG) ||
01571                                       (type == SSUPPL_TYPE_OUTPUT_NET) || (type == SSUPPL_TYPE_OUTPUT_REG) ||
01572                                       (type == SSUPPL_TYPE_INOUT_NET)  || (type == SSUPPL_TYPE_INOUT_REG)) &&
01573                                      (prange != NULL) && prange->dim[0].implicit &&
01574                                      (prange->dim[0].left->exp == NULL) && (prange->dim[0].left->num == 0) &&
01575                                      (prange->dim[0].right->exp == NULL) && (prange->dim[0].right->num == 0)) ? 1 : 0;
01576 
01577   }
01578 
01579   PROFILE_END;
01580   
01581 }

void db_add_statement statement stmt,
statement start
 

Adds specified statement to current functional unit's statement list. Called by parser.

Adds the specified statement tree to the tail of the current module's statement list. The start statement is specified to avoid infinite looping.

Parameters:
stmt  Pointer to statement add to current module's statement list
start  Pointer to starting statement of statement tree

02369   { PROFILE(DB_ADD_STATEMENT);
02370  
02371   if( (stmt != NULL) && (stmt->suppl.part.added == 0) ) {
02372 
02373 #ifdef DEBUG_MODE
02374     if( debug_mode ) {
02375       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_statement, id: %d, start id: %d", stmt->exp->id, start->exp->id );
02376       assert( rv < USER_MSG_LENGTH );
02377       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02378     }
02379 #endif
02380 
02381     /* Now add current statement */
02382     if( generate_top_mode > 0 ) {
02383 
02384       last_gi = gen_item_create_stmt( stmt );
02385 
02386       if( curr_gi_block != NULL ) {
02387         db_gen_item_connect( curr_gi_block, last_gi );
02388       } else {
02389         curr_gi_block = last_gi;
02390       }
02391 
02392     } else {
02393 
02394       /* Add the associated expression tree */
02395       db_add_expression( stmt->exp );
02396 
02397       /* Add TRUE and FALSE statement paths to list */
02398       if( (stmt->suppl.part.stop_false == 0) && (stmt->next_false != start) ) {
02399         db_add_statement( stmt->next_false, start );
02400       }
02401 
02402       if( (stmt->suppl.part.stop_true == 0) && (stmt->next_true != stmt->next_false) && (stmt->next_true != start) ) {
02403         db_add_statement( stmt->next_true, start );
02404       }
02405 
02406       /* Set ADDED bit of this statement */
02407       stmt->suppl.part.added = 1;
02408 
02409       /* Finally, add the statement to the functional unit statement list */
02410       stmt_link_add_tail( stmt, &(curr_funit->stmt_head), &(curr_funit->stmt_tail) );
02411 
02412     }
02413 
02414   }
02415 
02416   PROFILE_END;
02417 
02418 }

void db_add_typedef const char *  name,
bool  is_signed,
bool  is_handled,
bool  is_sizeable,
sig_range prange,
sig_range urange
 

Adds given typedefs to the database.

Adds the given names and information to the list of typedefs for the current module.

Parameters:
name  Typedef name for this type
is_signed  Specifies if this typedef is signed or not
is_handled  Specifies if this typedef is handled or not
is_sizeable  Specifies if a range can be later placed on this value
prange  Dimensional packed range information for this value
urange  Dimensional unpacked range information for this value

01634   { PROFILE(DB_ADD_TYPEDEF);
01635 
01636   typedef_item* tdi;   /* Typedef item to create */
01637 
01638 #ifdef DEBUG_MODE
01639   if( debug_mode ) {
01640     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_add_typedef, name: %s, is_signed: %d, is_handled: %d, is_sizeable: %d",
01641                                 name, is_signed, is_handled, is_sizeable );
01642     assert( rv < USER_MSG_LENGTH );
01643     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01644   }
01645 #endif
01646 
01647   /* Allocate memory and initialize the structure */
01648   tdi              = (typedef_item*)malloc_safe( sizeof( typedef_item ) );
01649   tdi->name        = strdup_safe( name );
01650   tdi->is_signed   = is_signed;
01651   tdi->is_handled  = is_handled;
01652   tdi->is_sizeable = is_sizeable;
01653   tdi->prange      = prange;
01654   tdi->urange      = urange;
01655   tdi->next        = NULL;
01656 
01657   /* Add it the current module's typedef list */
01658   if( curr_funit->tdi_head == NULL ) {
01659     curr_funit->tdi_head = curr_funit->tdi_tail = tdi;
01660   } else {
01661     curr_funit->tdi_tail->next = tdi;
01662     curr_funit->tdi_tail       = tdi;
01663   }
01664 
01665   /* Specify that the prange and urange expressions should not be deallocated */
01666   if( prange != NULL ) {
01667     prange->exp_dealloc = FALSE;
01668   }
01669   if( urange != NULL ) {
01670     urange->exp_dealloc = FALSE;
01671   }
01672 
01673   PROFILE_END;
01674 
01675 }

void db_assign_symbol const char *  name,
const char *  symbol,
int  msb,
int  lsb
 

Adds symbol to signal specified by name.

Creates a new entry in the symbol table for the specified signal and symbol.

Parameters:
name  Name of signal to set value to
symbol  Symbol value of signal used in VCD dumpfile
msb  Most significant bit of symbol to set
lsb  Least significant bit of symbol to set

02937   { PROFILE(DB_ASSIGN_SYMBOL);
02938 
02939 #ifdef DEBUG_MODE
02940   if( debug_mode ) {
02941     char*        scope = db_gen_curr_inst_scope();
02942     unsigned int rv    = snprintf( user_msg, USER_MSG_LENGTH, "In db_assign_symbol, name: %s, symbol: %s, curr_inst_scope: %s, msb: %d, lsb: %d",
02943                                    obf_sig( name ), symbol, obf_inst( scope ), msb, lsb );
02944     assert( rv < USER_MSG_LENGTH );
02945     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02946     free_safe( scope, (strlen( scope ) + 1) );
02947   }
02948 #endif
02949 
02950   assert( name != NULL );
02951 
02952   if( (curr_instance != NULL) && (curr_instance->funit != NULL) ) {
02953 
02954     sig_link*  sigl;
02955     vsignal*   sig;
02956     func_unit* found_funit;
02957     
02958     /* Find the signal that matches the specified signal name */
02959     if( ((sigl = sig_link_find( name, curr_instance->funit->sig_head )) != NULL) ||
02960         scope_find_signal( name, curr_instance->funit, &sig, &found_funit, 0 ) ) {
02961 
02962       /* If the signal exists in the current scope, assign the signal pointer to our temporary pointer */
02963       if( sigl != NULL ) {
02964         sig = sigl->sig;
02965       }
02966 
02967       /* Only add the symbol if we are not going to generate this value ourselves */
02968       if( (sig->suppl.part.assigned == 0)                  &&
02969           (sig->suppl.part.type != SSUPPL_TYPE_PARAM)      &&
02970           (sig->suppl.part.type != SSUPPL_TYPE_PARAM_REAL) &&
02971           (sig->suppl.part.type != SSUPPL_TYPE_ENUM)       &&
02972           (sig->suppl.part.type != SSUPPL_TYPE_MEM)        &&
02973           (sig->suppl.part.type != SSUPPL_TYPE_GENVAR)     &&
02974           (sig->suppl.part.type != SSUPPL_TYPE_EVENT) ) {
02975 
02976         /* Add this signal */
02977         symtable_add( symbol, sig, msb, lsb );
02978 
02979       }
02980 
02981     }
02982 
02983   }
02984 
02985   PROFILE_END;
02986 
02987 }

void db_bind_expr_tree expression root,
char *  sig_name
 

Binds all necessary sub-expressions in the given tree to the given signal name.

Recursively iterates through the entire expression tree binding all selection expressions within that tree to the given signal.

Parameters:
root  Pointer to root of expression tree to bind
sig_name  Name of signal to bind to

02021   { PROFILE(DB_BIND_EXPR_TREE);
02022 
02023   assert( sig_name != NULL );
02024 
02025   if( root != NULL ) {
02026 
02027 #ifdef DEBUG_MODE
02028     if( debug_mode ) {
02029       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_bind_expr_tree, root id: %d, sig_name: %s", root->id, sig_name );
02030       assert( rv < USER_MSG_LENGTH );
02031       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02032     }
02033 #endif
02034 
02035     /* Bind the children first */
02036     db_bind_expr_tree( root->left,  sig_name );
02037     db_bind_expr_tree( root->right, sig_name );
02038 
02039     /* Now bind ourselves if necessary */
02040     if( (root->op == EXP_OP_SBIT_SEL) ||
02041         (root->op == EXP_OP_MBIT_SEL) ||
02042         (root->op == EXP_OP_MBIT_POS) ||
02043         (root->op == EXP_OP_MBIT_NEG) ) {
02044       bind_add( 0, sig_name, root, curr_funit );
02045     }
02046 
02047   }
02048 
02049   PROFILE_END;
02050 
02051 }

bool db_check_for_top_module  ) 
 

Checks to see if the module specified by the -t option is the top-level module of the simulator.

Returns:
Returns TRUE if the top module specified in the -t option is the top-level module of the simulation; otherwise, returns FALSE.
Iterates through the signal list of the top-level module. Returns TRUE if no signals with type INPUT, OUTPUT or INOUT were found; otherwise, returns FALSE. Called by the parse_design() function.

00311                                { PROFILE(DB_CHECK_FOR_TOP_MODULE);
00312 
00313   bool        retval;
00314   funit_inst* top_inst;
00315 
00316   /* Get the top-most instance */
00317   instance_get_leading_hierarchy( db_list[curr_db]->inst_tail->inst, NULL, &top_inst );
00318 
00319   /* Check to see if the signal list is void of ports */
00320   retval = funit_is_top_module( top_inst->funit );
00321 
00322   PROFILE_END;
00323 
00324   return( retval );
00325 
00326 }

void db_close  ) 
 

Deallocates all memory consumed by the database.

Deallocates all memory associated with the databases.

00235                 { PROFILE(DB_CLOSE);
00236   
00237   unsigned int i, j;
00238 
00239   for( i=0; i<db_size; i++ ) {
00240 
00241     if( db_list[i]->inst_head != NULL ) {
00242 
00243       /* Remove memory allocated for inst_head */
00244       inst_link_delete_list( db_list[i]->inst_head );
00245       db_list[i]->inst_head = NULL;
00246       db_list[i]->inst_tail = NULL;
00247 
00248       /* Remove memory allocated for all functional units */
00249       funit_link_delete_list( &(db_list[i]->funit_head), &(db_list[i]->funit_tail), TRUE );
00250 
00251     }
00252 
00253     /* Deallocate all information regarding hierarchies */
00254     for( j=0; j<db_list[i]->leading_hier_num; j++ ) {
00255       free_safe( db_list[i]->leading_hierarchies[j], (strlen( db_list[i]->leading_hierarchies[j] ) + 1) );
00256     }
00257     free_safe( db_list[i]->leading_hierarchies, (sizeof( char* ) * db_list[i]->leading_hier_num) );
00258 
00259     /* Deallocate the file version information */
00260     str_link_delete_list( db_list[i]->fver_head );
00261     db_list[i]->fver_head = NULL;
00262     db_list[i]->fver_tail = NULL;
00263 
00264     /* Deallocate database structure */
00265     free_safe( db_list[i], sizeof( db ) );
00266 
00267   }
00268 
00269   /* Clear the global functional unit */
00270   global_funit = NULL;
00271 
00272   /* Deallocate preprocessor define tree */
00273   tree_dealloc( def_table );
00274   def_table = NULL;
00275 
00276   /* Deallocate the binding list */
00277   bind_dealloc();
00278 
00279   /* Deallocate database information */
00280   info_dealloc();
00281 
00282   /* Deallocate the needed module list */
00283   str_link_delete_list( modlist_head );
00284   modlist_head = NULL;
00285   modlist_tail = NULL;
00286     
00287   /* Free memory associated with current instance scope */
00288   assert( curr_inst_scope_size == 0 );
00289 
00290   /* Deallocate the exclusion identifier container, if it exists */
00291   free_safe( exclusion_id, db_get_exclusion_id_size() );
00292 
00293   /* Finally, deallocate the database list */
00294   free_safe( db_list, (sizeof( db ) * db_size) );
00295   db_list = NULL;
00296   db_size = 0;
00297   curr_db = 0;
00298 
00299   PROFILE_END;
00300 
00301 }

void db_connect_statement_false statement stmt,
statement next_false
 

Connects false statement to specified statement.

Connects the specified statement's false statement.

Parameters:
stmt  Pointer to statement to connect false path to
next_false  Pointer to statement to run if statement evaluates to FALSE

02537   { PROFILE(DB_CONNECT_STATEMENT_FALSE);
02538 
02539 #ifdef DEBUG_MODE
02540   int next_id;  /* Statement ID of next FALSE statement */
02541 #endif
02542 
02543   if( stmt != NULL ) {
02544 
02545 #ifdef DEBUG_MODE
02546     if( debug_mode ) {
02547       unsigned int rv;
02548       if( next_false == NULL ) {
02549         next_id = 0;
02550       } else {
02551         next_id = next_false->exp->id;
02552       }
02553 
02554       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_connect_statement_false, id: %d, next: %d", stmt->exp->id, next_id );
02555       assert( rv < USER_MSG_LENGTH );
02556       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02557     }
02558 #endif
02559 
02560     stmt->next_false = next_false;
02561 
02562   }
02563 
02564   PROFILE_END;
02565 
02566 }

void db_connect_statement_true statement stmt,
statement next_true
 

Connects true statement to specified statement.

Connects the specified statement's true statement.

Parameters:
stmt  Pointer to statement to connect true path to
next_true  Pointer to statement to run if statement evaluates to TRUE

02500   { PROFILE(DB_CONNECT_STATEMENT_TRUE);
02501 
02502 #ifdef DEBUG_MODE
02503   int next_id;  /* Statement ID of next TRUE statement */
02504 #endif
02505 
02506   if( stmt != NULL ) {
02507 
02508 #ifdef DEBUG_MODE
02509     if( debug_mode ) {
02510       unsigned int rv;
02511       if( next_true == NULL ) {
02512         next_id = 0;
02513       } else {
02514         next_id = next_true->exp->id;
02515       }
02516 
02517       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_connect_statement_true, id: %d, next: %d", stmt->exp->id, next_id );
02518       assert( rv < USER_MSG_LENGTH );
02519       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02520     }
02521 #endif
02522 
02523     stmt->next_true = next_true;
02524 
02525   }
02526 
02527   PROFILE_END;
02528 
02529 }

db* db_create  ) 
 

Creates a new database.

Returns:
Returns pointer to newly allocated and initialized database structure
Allocates, initializes and stores new database structure into global database array.

00205                 { PROFILE(DB_CREATE);
00206 
00207   db* new_db;  /* Pointer to new database structure */
00208 
00209   /* Allocate new database */
00210   new_db                       = (db*)malloc_safe( sizeof( db ) );
00211   new_db->inst_head            = NULL;
00212   new_db->inst_tail            = NULL;
00213   new_db->funit_head           = NULL;
00214   new_db->funit_tail           = NULL;
00215   new_db->fver_head            = NULL;
00216   new_db->fver_tail            = NULL;
00217   new_db->leading_hierarchies  = NULL;
00218   new_db->leading_hier_num     = 0;
00219   new_db->leading_hiers_differ = FALSE;
00220 
00221   /* Add this new database to the database array */
00222   db_list = (db**)realloc_safe( db_list, (sizeof( db ) * db_size), (sizeof( db ) * (db_size + 1)) );
00223   db_list[db_size] = new_db;
00224   db_size++;
00225 
00226   PROFILE_END;
00227 
00228   return( new_db );
00229 
00230 }

attr_param* db_create_attr_param char *  name,
expression expr
 

Allocates and initializes an attribute parameter.

Returns:
Returns a pointer to the newly created attribute parameter.
Calls the attribute_create() function and returns the pointer returned by this function.
Parameters:
name  Attribute parameter identifier
expr  Pointer to constant expression that is assigned to the identifier

02714   { PROFILE(DB_CREATE_ATTR_PARAM);
02715 
02716   attr_param* attr;  /* Pointer to newly allocated/initialized attribute parameter */
02717 
02718 #ifdef DEBUG_MODE
02719   if( debug_mode ) {
02720     unsigned int rv;
02721     if( expr != NULL ) {
02722       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_create_attr_param, name: %s, expr: %d", name, expr->id );
02723     } else {
02724       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_create_attr_param, name: %s", name );
02725     }
02726     assert( rv < USER_MSG_LENGTH );
02727     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02728   }
02729 #endif
02730 
02731   attr = attribute_create( name, expr );
02732 
02733   PROFILE_END;
02734 
02735   return( attr );
02736 
02737 }

expression* db_create_expr_from_static static_expr se,
int  line,
int  first_col,
int  last_col
 

Creates an expression from the specified static expression.

Returns:
Returns a pointer to an expression that represents the static expression specified
Exceptions:
anonymous db_create_expression Throw
Creates an expression structure from a static expression structure.
Parameters:
se  Pointer to static expression structure
line  Line number that static expression was found on
first_col  Column that the static expression starts on
last_col  Column that the static expression ends on

02065   { PROFILE(DB_CREATE_EXPR_FROM_STATIC);
02066 
02067   expression* expr = NULL;  /* Return value for this function */
02068   vector*     vec;          /* Temporary vector */
02069 
02070 #ifdef DEBUG_MODE
02071   if( debug_mode ) {
02072     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_create_expr_from_static, se: %p, line: %d, first_col: %d, last_col: %d",
02073                                 se, line, first_col, last_col );
02074     assert( rv < USER_MSG_LENGTH );
02075     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02076   }
02077 #endif
02078 
02079   Try {
02080 
02081     if( se->exp == NULL ) {
02082 
02083       /* This static expression is a static value so create a static expression from its value */
02084       expr = db_create_expression( NULL, NULL, EXP_OP_STATIC, FALSE, line, first_col, last_col, NULL );
02085 
02086       /* Create the new vector */
02087       vec = vector_create( 32, VTYPE_VAL, VDATA_UL, TRUE );
02088       (void)vector_from_int( vec, se->num );
02089 
02090       /* Assign the new vector to the expression's vector (after deallocating the expression's old vector) */
02091       assert( expr->value->value.ul == NULL );
02092       free_safe( expr->value, sizeof( vector ) );
02093       expr->value = vec;
02094 
02095     } else {
02096 
02097       /* The static expression is unresolved, so just get its expression */
02098       expr = se->exp;
02099 
02100     }
02101 
02102   } Catch_anonymous {
02103     static_expr_dealloc( se, FALSE );
02104     Throw 0;
02105   }
02106 
02107   /* Deallocate static expression */
02108   static_expr_dealloc( se, FALSE );
02109 
02110   PROFILE_END;
02111 
02112   return( expr );
02113 
02114 }

expression* db_create_expression expression right,
expression left,
exp_op_type  op,
bool  lhs,
int  line,
int  first,
int  last,
char *  sig_name
 

Creates new expression from specified information. Called by parser and db_add_expression.

Returns:
Returns pointer to newly created expression.
Exceptions:
anonymous expression_create Throw
Creates a new expression with the specified parameter information and returns a pointer to the newly created expression.
Parameters:
right  Pointer to expression on right side of expression
left  Pointer to expression on left side of expression
op  Operation to perform on expression
lhs  Specifies this expression is a left-hand-side assignment expression
line  Line number of current expression
first  Column index of first character in this expression
last  Column index of last character in this expression
sig_name  Name of signal that expression is attached to (if valid)

01879   { PROFILE(DB_CREATE_EXPRESSION);
01880 
01881   expression* expr;        /* Temporary pointer to newly created expression */
01882   func_unit*  func_funit;  /* Pointer to function, if we are nested in one */
01883 
01884 #ifdef DEBUG_MODE
01885   if( debug_mode ) {
01886     int          right_id;    /* ID of right expression */
01887     int          left_id;     /* ID of left expression */
01888     unsigned int rv;          /* Return value from snprintf call */
01889 
01890     if( right == NULL ) {
01891       right_id = 0;
01892     } else {
01893       right_id = right->id;
01894     }
01895 
01896     if( left == NULL ) {
01897       left_id = 0;
01898     } else {
01899       left_id = left->id;
01900     }
01901 
01902     if( sig_name == NULL ) {
01903       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_create_expression, right: %d, left: %d, id: %d, op: %s, lhs: %d, line: %d, first: %d, last: %d", 
01904                      right_id, left_id, curr_expr_id, expression_string_op( op ), lhs, line, first, last );
01905     } else {
01906       rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_create_expression, right: %d, left: %d, id: %d, op: %s, lhs: %d, line: %d, first: %d, last: %d, sig_name: %s",
01907                      right_id, left_id, curr_expr_id, expression_string_op( op ), lhs, line, first, last, sig_name );
01908     }
01909     assert( rv < USER_MSG_LENGTH );
01910     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01911   }
01912 #endif
01913 
01914   /* Check to see if current expression is in a function */
01915   func_funit = funit_get_curr_function( curr_funit );
01916 
01917   /* Check to make sure that expression is allowed for the current functional unit type */
01918   if( (func_funit != NULL) &&
01919       ((op == EXP_OP_DELAY) ||
01920        (op == EXP_OP_TASK_CALL) ||
01921        (op == EXP_OP_NASSIGN)   ||
01922        (op == EXP_OP_PEDGE)     ||
01923        (op == EXP_OP_NEDGE)     ||
01924        (op == EXP_OP_AEDGE)     ||
01925        (op == EXP_OP_EOR)) ) {
01926     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Attempting to use a delay, task call, non-blocking assign or event controls in function %s, file %s, line %d",
01927                                 obf_funit( func_funit->name ), obf_file( curr_funit->filename ), line );
01928     assert( rv < USER_MSG_LENGTH );
01929     print_output( user_msg, FATAL, __FILE__, __LINE__ );
01930     Throw 0;
01931   }
01932 
01933   /* Create expression with next expression ID */
01934   expr = expression_create( right, left, op, lhs, curr_expr_id, line, first, last, FALSE );
01935   curr_expr_id++;
01936 
01937   /* If current functional unit is nested in a function, set the IN_FUNC supplemental field bit */
01938   expr->suppl.part.in_func = (func_funit != NULL) ? 1 : 0;
01939 
01940   /* Set the clear_changed bit if any of our children have their clear_changed bit set or if we are a system function expression */
01941   if( ((left  != NULL) && 
01942        ((left->suppl.part.clear_changed == 1) ||
01943         (left->op == EXP_OP_STIME) || (left->op == EXP_OP_SRANDOM) || (left->op == EXP_OP_SURANDOM) || (left->op == EXP_OP_SURAND_RANGE) ||
01944         (left->op == EXP_OP_SB2R)  || (left->op == EXP_OP_SR2B)    || (left->op == EXP_OP_SI2R)     || (left->op == EXP_OP_SR2I) ||
01945         (left->op == EXP_OP_SB2SR) || (left->op == EXP_OP_SSR2B))) ||
01946       ((right != NULL) &&
01947        ((right->suppl.part.clear_changed == 1) ||
01948         (right->op == EXP_OP_STIME) || (right->op == EXP_OP_SRANDOM) || (right->op == EXP_OP_SURANDOM) || (right->op == EXP_OP_SURAND_RANGE) ||
01949         (right->op == EXP_OP_SB2R)  || (right->op == EXP_OP_SR2B)    || (right->op == EXP_OP_SI2R)     || (right->op == EXP_OP_SR2I) ||
01950         (right->op == EXP_OP_SB2SR) || (right->op == EXP_OP_SSR2B))) ) {
01951     expr->suppl.part.clear_changed = 1;
01952   }
01953 
01954   /* If we are in exclude mode, set the exclude and stmt_exclude bits */
01955   if( exclude_mode > 0 ) {
01956     expr->suppl.part.excluded = 1;
01957   }
01958 
01959   /* If this expression is in the for control, set its bit */
01960   if( for_mode > 0 ) {
01961     expr->suppl.part.for_cntrl = 1;
01962   }
01963 
01964   /*
01965    If this is some kind of assignment expression operator, set the our expression vector to that of
01966    the right expression.
01967   */
01968   if( (expr->op == EXP_OP_BASSIGN) ||
01969       (expr->op == EXP_OP_NASSIGN) ||
01970       (expr->op == EXP_OP_RASSIGN) ||
01971       (expr->op == EXP_OP_DASSIGN) ||
01972       (expr->op == EXP_OP_ASSIGN)  ||
01973       (expr->op == EXP_OP_IF)      ||
01974       (expr->op == EXP_OP_WHILE)   ||
01975       (expr->op == EXP_OP_DIM)     ||
01976       (expr->op == EXP_OP_DLY_ASSIGN) ) {
01977     vector_dealloc( expr->value );
01978     expr->suppl.part.owns_vec = 0;
01979     expr->value = right->value;
01980   }
01981 
01982   /* Add expression and signal to binding list */
01983   if( sig_name != NULL ) {
01984 
01985     /*
01986      If we are in a generate block and the signal name contains a generate variable/expression,
01987      create a generate item to handle the binding later.
01988     */
01989     if( (generate_mode > 0) && gen_item_varname_contains_genvar( sig_name ) ) {
01990       last_gi = gen_item_create_bind( sig_name, expr );
01991       if( curr_gi_block != NULL ) {
01992         db_gen_item_connect( curr_gi_block, last_gi );
01993       } else {
01994         curr_gi_block = last_gi;
01995       }
01996     } else {
01997       switch( op ) {
01998         case EXP_OP_FUNC_CALL :  bind_add( FUNIT_FUNCTION,    sig_name, expr, curr_funit );  break;
01999         case EXP_OP_TASK_CALL :  bind_add( FUNIT_TASK,        sig_name, expr, curr_funit );  break;
02000         case EXP_OP_NB_CALL   :  bind_add( FUNIT_NAMED_BLOCK, sig_name, expr, curr_funit );  break;
02001         case EXP_OP_DISABLE   :  bind_add( 1,                 sig_name, expr, curr_funit );  break;
02002         default               :  bind_add( 0,                 sig_name, expr, curr_funit );  break;
02003       }
02004     }
02005 
02006   }
02007 
02008   PROFILE_END;
02009  
02010   return( expr );
02011 
02012 }

expression* db_create_sensitivity_list statement stmt  ) 
 

Creates an expression tree sensitivity list for the given statement block.

Returns:
Returns expression tree to execute a sensitivity list for the given statement block.
Exceptions:
anonymous db_create_expression db_create_expression db_create_expression db_create_expression Throw
Parameters:
stmt  Pointer to statement block to parse

02177   { PROFILE(DB_CREATE_SENSITIVITY_LIST);
02178 
02179   str_link*   sig_head = NULL;  /* Pointer to head of signal name list containing RHS used signals */
02180   str_link*   sig_tail = NULL;  /* Pointer to tail of signal name list containing RHS used signals */
02181   str_link*   strl;             /* Pointer to current signal name link */
02182   expression* exps;             /* Pointer to created expression for type SIG */
02183   expression* expa;             /* Pointer to created expression for type AEDGE */
02184   expression* expe;             /* Pointer to created expression for type EOR */
02185   expression* expc     = NULL;  /* Pointer to left child expression */
02186 
02187   /* Get the list of all RHS signals in the given statement block */
02188   statement_find_rhs_sigs( stmt, &sig_head, &sig_tail );
02189 
02190   /* Create sensitivity expression tree for the list of RHS signals */
02191   if( sig_head != NULL ) {
02192 
02193     Try {
02194 
02195       strl = sig_head;
02196       while( strl != NULL ) {
02197 
02198         /* Create AEDGE and EOR for subsequent signals */
02199         exps = db_create_expression( NULL, NULL, EXP_OP_SIG,   FALSE, 0, 0, 0, strl->str );
02200         expa = db_create_expression( exps, NULL, EXP_OP_AEDGE, FALSE, 0, 0, 0, NULL );
02201 
02202         /* If we have a child expression already, create the EOR expression to connect them */
02203         if( expc != NULL ) {
02204           expe = db_create_expression( expa, expc, EXP_OP_EOR, FALSE, 0, 0, 0, NULL );
02205           expc = expe;
02206         } else {
02207           expc = expa;
02208         }
02209 
02210         strl = strl->next;
02211 
02212       }
02213 
02214     } Catch_anonymous {
02215       str_link_delete_list( sig_head );
02216       Throw 0;
02217     }
02218 
02219     /* Deallocate string list */
02220     str_link_delete_list( sig_head );
02221 
02222   }
02223 
02224   PROFILE_END;
02225 
02226   return( expc );
02227 
02228 }

statement* db_create_statement expression exp,
unsigned int  ppline
 

Creates new statement expression from specified information. Called by parser.

Returns:
Returns pointer to created statement.
Exceptions:
anonymous db_parallelize_statement Throw
Creates an statement structure and adds created statement to current module's statement list.
Parameters:
exp  Pointer to associated "root" expression
ppline  First line of the statement in the preprocessor file

02315   { PROFILE(DB_CREATE_STATEMENT);
02316 
02317   statement* stmt = NULL;  /* Pointer to newly created statement */
02318 
02319   /* If the statement expression is NULL, we can't create the statement */
02320   if( exp != NULL ) {
02321 
02322 #ifdef DEBUG_MODE
02323     if( debug_mode ) {
02324       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_create_statement, id: %d, line: %d", exp->id, exp->line );
02325       assert( rv < USER_MSG_LENGTH );
02326       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02327     }
02328 #endif
02329 
02330     /* Create the given statement */
02331     stmt = statement_create( exp, curr_funit, ppline );
02332 
02333     /* If we are in the exclude mode, exclude this statement */
02334     if( exclude_mode > 0 ) {
02335       stmt->suppl.part.excluded = 1;
02336     }
02337 
02338     /* If we need to exclude this statement from race condition checking, do so */
02339     if( ignore_racecheck_mode > 0 ) {
02340       stmt->suppl.part.ignore_rc = 1;
02341     }
02342 
02343     Try {
02344 
02345       /* If we are a parallel statement, create a FORK statement for this statement block */
02346       stmt = db_parallelize_statement( stmt );
02347 
02348     } Catch_anonymous {
02349       statement_dealloc( stmt );
02350       expression_dealloc( exp, FALSE );
02351       Throw 0;
02352     }
02353 
02354   }
02355 
02356   PROFILE_END;
02357 
02358   return( stmt );
02359 
02360 }

char* db_create_unnamed_scope  ) 
 

Creates a scope name for an unnamed scope. Called only during parsing.

Returns:
Returns a scope name for an unnamed scope. Only called for parsing purposes.

00794                                 { PROFILE(DB_CREATE_UNNAMED_SCOPE);
00795 
00796   char         tmpname[30];
00797   char*        name;
00798   unsigned int rv = snprintf( tmpname, 30, "$u%d", unnamed_scope_id );
00799 
00800   assert( rv < 30 );
00801   
00802   name = strdup_safe( tmpname );
00803   unnamed_scope_id++;
00804 
00805   PROFILE_END;
00806 
00807   return( name );
00808 
00809 }

bool db_do_timestep uint64  time,
bool  final
 

Performs a timestep for all signal changes during this timestep.

Returns:
Returns TRUE if simulation should continue to advance; otherwise, returns FALSE to indicate that simulation should stop immediately.
Exceptions:
anonymous symtable_assign
Cycles through expression queue, performing expression evaluations as we go. If an expression has a parent expression, that parent expression is placed in the expression queue after that expression has completed its evaluation. When the expression queue is empty, we are finished for this clock period.
Parameters:
time  Current time step value being performed
final  Specifies that this is the final timestep

03061   { PROFILE(DB_DO_TIMESTEP);
03062 
03063   bool            retval;               /* Return value for this function */
03064   static sim_time curr_time;
03065   static uint64   last_sim_update = 0;
03066 
03067 #ifdef DEBUG_MODE
03068   if( debug_mode ) {
03069     if( final ) {
03070       print_output( "Performing final timestep", DEBUG, __FILE__, __LINE__ );
03071     } else {
03072       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Performing timestep #%lld", time );
03073       assert( rv < USER_MSG_LENGTH );
03074       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
03075     }
03076   }
03077 #endif
03078 
03079   num_timesteps++;
03080 
03081   curr_time.lo    = (time & 0xffffffffLL);
03082   curr_time.hi    = ((time >> 32) & 0xffffffffLL);
03083   curr_time.full  = time;
03084   curr_time.final = final;
03085 
03086   if( (timestep_update > 0) && ((time - last_sim_update) >= timestep_update) && !debug_mode && !final ) {
03087     unsigned int rv;
03088     last_sim_update = time;
03089     /*@-formattype -duplicatequals@*/
03090     printf( "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bPerforming timestep %10llu", time );
03091     /*@=formattype =duplicatequals@*/
03092     rv = fflush( stdout );
03093     assert( rv == 0 );
03094   }
03095 
03096   /* Simulate the current timestep */
03097   retval = sim_simulate( &curr_time );
03098 
03099   /* If this is the last timestep, add the final list and do one more simulate */
03100   if( final && retval ) {
03101     curr_time.lo   = 0xffffffff;
03102     curr_time.hi   = 0xffffffff;
03103     curr_time.full = 0xffffffffffffffffLL;
03104     retval = sim_simulate( &curr_time );
03105   }
03106 
03107 #ifdef DEBUG_MODE
03108   if( debug_mode ) {
03109     print_output( "Assigning postsimulation signals...", DEBUG, __FILE__, __LINE__ );
03110   }
03111 #endif
03112 
03113   if( retval ) {
03114 
03115     /* Assign all stored values in current post-timestep to stored signals */
03116     symtable_assign( &curr_time );
03117 
03118     /* Perform non-blocking assignment */
03119     sim_perform_nba( &curr_time );
03120 
03121   }
03122 
03123   PROFILE_END;
03124 
03125   return( retval );
03126 
03127 }

void db_end_enum_list  ) 
 

Called after all enumerated values for the current list have been added.

Called after an entire enum list has been parsed and added to the database.

01610                         { PROFILE(DB_END_ENUM_LIST);
01611 
01612 #ifdef DEBUG_MODE
01613   if( debug_mode ) {
01614     print_output( "In db_end_enum_list", DEBUG, __FILE__, __LINE__ );
01615   }
01616 #endif 
01617 
01618   enumerate_end_list( curr_funit );
01619 
01620   PROFILE_END;
01621 
01622 }

void db_end_function_task int  end_line  ) 
 

Called when the endfunction or endtask keyword is parsed.

void db_end_function_task_namedblock int  end_line  ) 
 

Performs actions necessary when the end of a function/task/named-block is seen. Called by parser.

Causes the current function/task/named block to be ended and added to the database.

Parameters:
end_line  Line number of end of this task/function

01256   { PROFILE(DB_END_FUNCTION_TASK_NAMEDBLOCK);
01257 
01258   stmt_iter si;  /* Statement iterator for finding the first statement of the functional unit */
01259 
01260 #ifdef DEBUG_MODE
01261   if( debug_mode ) {
01262     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_end_function_task_namedblock, end_line: %d", end_line );
01263     assert( rv < USER_MSG_LENGTH );
01264     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01265   }
01266 #endif
01267 
01268   /* Store last line information */
01269   curr_funit->end_line = end_line;
01270 
01271   /* Set the first statement pointer */
01272   if( curr_funit->stmt_head != NULL ) {
01273 
01274     assert( curr_funit->stmt_head->stmt != NULL );
01275 
01276     /* Set functional unit's first_stmt pointer to its head statement */
01277     stmt_iter_reset( &si, curr_funit->stmt_tail );
01278     stmt_iter_find_head( &si, FALSE );
01279 
01280     if( si.curr->stmt != NULL ) {
01281       curr_funit->first_stmt = si.curr->stmt;
01282     }
01283 
01284   }
01285 
01286   /* Set the current functional unit to the parent module */
01287   curr_funit = curr_funit->parent;
01288 
01289   PROFILE_END;
01290 
01291 }

void db_end_module int  end_line  ) 
 

Called when the endmodule keyword is parsed.

Updates the modlist for parsing purposes.

Parameters:
end_line  Ending line number of specified module in file

01147   { PROFILE(DB_END_MODULE);
01148 
01149 #ifdef DEBUG_MODE
01150   if( debug_mode ) {
01151     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_end_module, end_line: %d", end_line );
01152     assert( rv < USER_MSG_LENGTH );
01153     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01154   }
01155 #endif
01156 
01157   curr_funit->end_line = end_line;
01158 
01159   str_link_remove( curr_funit->name, &modlist_head, &modlist_tail );
01160 
01161   /* Return the current functional unit to the global functional unit, if it exists */
01162   curr_funit = global_funit;
01163 
01164   PROFILE_END;
01165 
01166 }

gen_item* db_find_gen_item gen_item root,
gen_item gi
 

Find specified generate item in the current functional unit. Called by parser.

Returns:
Returns pointer to found matching generate item (NULL if not found)
Searches the current functional unit for the generate item that matches the specified generate item. If it is found, a pointer to the stored generate item is returned. If it is not found, a value of NULL is returned. Additionally, the specified generate item is automatically deallocated on behalf of the caller. This function should only be called during the parsing stage.
Parameters:
root  Pointer to root generate item to start searching in
gi  Pointer to created generate item to search for

01748   { PROFILE(DB_FIND_GEN_ITEM);
01749 
01750   gen_item* found;  /* Return value for this function */
01751 
01752 #ifdef DEBUG_MODE
01753   if( debug_mode ) {
01754     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_find_gen_item, type %d", gi->suppl.part.type );
01755     assert( rv < USER_MSG_LENGTH );
01756     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01757   }
01758 #endif
01759 
01760   /* Search for the specified generate item */
01761   found = gen_item_find( root, gi );
01762 
01763   /* Deallocate the user-specified generate item */
01764   gen_item_dealloc( gi, FALSE );
01765 
01766   PROFILE_END;
01767 
01768   return( found );
01769 
01770 }

vsignal* db_find_signal char *  name,
bool  okay_if_not_found
 

Finds specified signal in functional unit and returns pointer to the signal structure. Called by parser.

Returns:
Returns pointer to the found signal.
Exceptions:
anonymous Throw
Searches signal matching the specified name using normal scoping rules. If the signal is found, returns a pointer to the calling function for that signal. If the signal is not found, emits a user error and immediately halts execution.
Parameters:
name  String name of signal to find in current module
okay_if_not_found  If set to TRUE, does not emit error message if signal is not found (returns NULL)

01689   { PROFILE(DB_FIND_SIGNAL);
01690 
01691   vsignal*   found_sig;    /* Pointer to found signal (return value) */
01692   func_unit* found_funit;  /* Pointer to found functional unit (not used) */
01693 
01694 #ifdef DEBUG_MODE
01695   if( debug_mode ) {
01696     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_find_signal, searching for signal %s", obf_sig( name ) );
01697     assert( rv < USER_MSG_LENGTH );
01698     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01699   }
01700 #endif
01701 
01702   if( !scope_find_signal( name, curr_funit, &found_sig, &found_funit, 0 ) && !okay_if_not_found ) {
01703 
01704     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to find variable %s in module %s", obf_sig( name ), obf_funit( curr_funit->name ) );
01705     assert( rv < USER_MSG_LENGTH );
01706     print_output( user_msg, FATAL, __FILE__, __LINE__ );
01707     Throw 0;
01708 
01709   }
01710 
01711   PROFILE_END;
01712 
01713   return( found_sig );
01714 
01715 }

typedef_item* db_find_typedef const char *  name  ) 
 

Finds specified typedef and returns TRUE if it is found.

Returns:
Returns pointer to found typedef item or NULL if none was found.
Searches for the given typedef name in the current module.
Parameters:
name  Name of typedef to search for

01779   { PROFILE(DB_FIND_TYPEDEF);
01780 
01781   func_unit*    parent;      /* Pointer to parent module */
01782   typedef_item* tdi = NULL;  /* Pointer to current typedef item */
01783 
01784   assert( name != NULL );
01785 
01786 #ifdef DEBUG_MODE
01787   if( debug_mode ) {
01788     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_find_typedef, searching for name: %s", name );
01789     assert( rv < USER_MSG_LENGTH );
01790     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01791   }
01792 #endif
01793 
01794   if( curr_funit != NULL ) {
01795 
01796     parent = funit_get_curr_module( curr_funit );
01797 
01798     tdi = parent->tdi_head;
01799     while( (tdi != NULL) && (strcmp( tdi->name, name ) != 0) ) {
01800       tdi = tdi->next;
01801     }
01802 
01803     /* If we could not find the typedef in the current functional unit, look in the global funit, if it exists */
01804     if( (tdi == NULL) && (global_funit != NULL) ) {
01805       tdi = global_funit->tdi_head;
01806       while( (tdi != NULL) && (strcmp( tdi->name, name ) != 0) ) {
01807         tdi = tdi->next;
01808       }
01809     }
01810 
01811   }
01812 
01813   PROFILE_END;
01814 
01815   return( tdi );
01816 
01817 }

char* db_gen_exclusion_id char  type,
int  id
 

Allocates memory for and generates the exclusion identifier.

Returns:
Returns the generated exclusion ID given the parameters and the value of the report_exclusions global flag.
Generates the exclusion ID string and stores the result in the excl_id array.

Note:
This function should ONLY be called when the flag_output_exclusion_ids is set to TRUE.
Parameters:
type  Single character specifying the metric type (L, T, M, C, A, F)
id  Numerical unique identifier

00918   { PROFILE(DB_GEN_EXCLUSION_ID);
00919 
00920   char         tmp[30];
00921   int          size = db_get_exclusion_id_size();
00922   unsigned int rv;
00923 
00924   /* If the exclusion ID has not been created, create it now */
00925   if( exclusion_id == NULL ) {
00926 
00927     /* Allocate the memory needed */
00928     exclusion_id = (char*)malloc_safe( size );
00929 
00930   }
00931 
00932   /* Create format string */
00933   rv = snprintf( tmp, 30, "%%c%%0%dd", (size - 2) );
00934   assert( rv < 30 );
00935 
00936   /* Generate exclusion_id string */
00937   rv = snprintf( exclusion_id, size, tmp, type, id );
00938   assert( rv < size );
00939  
00940   PROFILE_END;
00941 
00942   return( exclusion_id );
00943  
00944 }

void db_gen_item_connect gen_item gi1,
gen_item gi2
 

Connects one generate item block to another.

Connects two generate items together.

Parameters:
gi1  Pointer to generate item block to connect to gi2
gi2  Pointer to generate item that will be connected to gi1

02622   { PROFILE(DB_GEN_ITEM_CONNECT);
02623 
02624   bool rv;
02625 
02626 #ifdef DEBUG_MODE
02627   if( debug_mode ) {
02628     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_gen_item_connect, gi1: %p, gi2: %p, conn_id: %d", gi1, gi2, gi_conn_id );
02629     assert( rv < USER_MSG_LENGTH );
02630     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02631   }
02632 #endif
02633 
02634   /* Connect generate items */
02635   rv = gen_item_connect( gi1, gi2, gi_conn_id, FALSE );
02636   assert( rv );
02637 
02638   /* Increment gi_conn_id for next connection */
02639   gi_conn_id++;
02640 
02641   PROFILE_END;
02642 
02643 }

void db_gen_item_connect_false gen_item gi1,
gen_item gi2
 

Connects gi2 to the false path of gi1.

Connects gi2 to gi1's next_false pointer.

Parameters:
gi1  Pointer to generate item holding next_false
gi2  Pointer to generate item to connect

02598   { PROFILE(DB_GEN_ITEM_CONNECT_FALSE);
02599 
02600   assert( gi1 != NULL );
02601 
02602 #ifdef DEBUG_MODE
02603   if( debug_mode ) {
02604     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_gen_item_connect_false, gi1: %p, gi2: %p", gi1, gi2 );
02605     assert( rv < USER_MSG_LENGTH );
02606     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02607   }
02608 #endif
02609 
02610   gi1->next_false = gi2;
02611 
02612   PROFILE_END;
02613 
02614 }

void db_gen_item_connect_true gen_item gi1,
gen_item gi2
 

Connects gi2 to the true path of gi1.

Connects gi2 to gi1's next_true pointer.

Parameters:
gi1  Pointer to generate item holding next_true
gi2  Pointer to generate item to connect

02574   { PROFILE(DB_GEN_ITEM_CONNECT_TRUE);
02575 
02576   assert( gi1 != NULL );
02577 
02578 #ifdef DEBUG_MODE
02579   if( debug_mode ) {
02580     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_gen_item_connect_true, gi1: %p, gi2: %p", gi1, gi2 );
02581     assert( rv < USER_MSG_LENGTH );
02582     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02583   }
02584 #endif
02585 
02586   gi1->next_true = gi2;  
02587 
02588   PROFILE_END;
02589 
02590 }

func_unit* db_get_curr_funit  ) 
 

Returns a pointer to the current functional unit.

Returns:
Returns a pointer to the current functional unit.
This function returns a pointer to the current functional unit being parsed.

00851                                { PROFILE(DB_GET_CURR_FUNIT);
00852 
00853   PROFILE_END;
00854 
00855   return( curr_funit );
00856 
00857 }

gen_item* db_get_curr_gen_block  ) 
 

Returns a pointer to the current implicitly connected generate block. Called by parser.

Returns:
Returns a pointer to the last generate item added to the current functional unit.

01822                                   { PROFILE(DB_GET_CURR_GEN_BLOCK);
01823 
01824   gen_item* block = curr_gi_block;  /* Temporary pointer to current generate item block */
01825 
01826 #ifdef DEBUG_MODE
01827   if( debug_mode ) {
01828     print_output( "In db_get_curr_gen_block", DEBUG, __FILE__, __LINE__ );
01829   }
01830 #endif
01831 
01832   /* Clear the curr_gi_block and last_gi pointers */
01833   curr_gi_block = NULL;
01834   last_gi       = NULL;
01835 
01836   PROFILE_END;
01837 
01838   return( block );
01839 
01840 }

unsigned int db_get_exclusion_id_size  ) 
 

Calculates and returns the size of the exclusion ID string.

Returns:
Returns the size needed to allocate for an entire exclusion ID.

00862                                         { PROFILE(DB_GET_EXCLUSION_ID_SIZE);
00863 
00864   static unsigned int exclusion_id_size = 0;
00865 
00866   if( exclusion_id_size == 0 ) {
00867 
00868     char         tmp[30];
00869     unsigned int rv;
00870 
00871     /* Calculate the size needed to store the largest signal ID */
00872     rv = snprintf( tmp, 30, "%d", curr_sig_id );
00873     assert( rv < 30 );
00874     exclusion_id_size = strlen( tmp ) + 2;
00875 
00876     /* Now calculate the size needed to store the largest expression ID */
00877     rv = snprintf( tmp, 30, "%d", curr_expr_id );
00878     assert( rv < 30 );
00879 
00880     /* Figure out which value is greater and use that for the size of the exclusion ID */
00881     if( (strlen( tmp ) + 2) > exclusion_id_size ) {
00882       exclusion_id_size = strlen( tmp ) + 2;
00883     }
00884 
00885     /* Now calculate the size needed to store the largest arc ID */
00886     rv = snprintf( tmp, 30, "%d", curr_arc_id );
00887     assert( rv < 30 );
00888 
00889     /* Figure out which value is greater and use that for the size of the exclusion ID */
00890     if( (strlen( tmp ) + 2) > exclusion_id_size ) {
00891       exclusion_id_size = strlen( tmp ) + 2;
00892     }
00893 
00894     /* The minimum size of the exclusion ID should be 3 characters */
00895     if( exclusion_id_size < 4 ) {
00896       exclusion_id_size = 4;
00897     }
00898 
00899   }
00900 
00901   PROFILE_END;
00902 
00903   return( exclusion_id_size );
00904 
00905 }

bool db_is_unnamed_scope char *  scope  ) 
 

Returns TRUE if the given scope is an unnamed scope name; otherwise, returns FALSE.

Returns:
Returns TRUE if the given scope is an unnamed scope name; otherwise, returns FALSE.
Parameters:
scope  Name to check

00816   { PROFILE(DB_IS_UNNAMED_SCOPE);
00817 
00818   bool is_unnamed = (scope != NULL) && (scope[0] == '$') && (scope[1] == 'u');
00819 
00820   PROFILE_END;
00821 
00822   return( is_unnamed );
00823 
00824 }

void db_merge_instance_trees  ) 
 

Merges the current instance trees.

Iterates through the instance tree list, merging all instances into the first instance tree that is not the $root instance tree.

00721                                { PROFILE(DB_MERGE_INSTANCE_TREES);
00722 
00723   funit_inst* base  = NULL;
00724   inst_link*  instl = db_list[curr_db]->inst_head;
00725   bool        done  = FALSE;
00726 
00727   /* Merge all root trees */
00728   instl = db_list[curr_db]->inst_head;
00729   while( instl != NULL ) {
00730     if( strcmp( instl->inst->name, "$root" ) == 0 ) {
00731       if( base == NULL ) {
00732         base        = instl->inst;
00733         instl->base = TRUE;
00734       } else {
00735         instl->ignore = instance_merge_two_trees( base, instl->inst );
00736       }
00737     }
00738     instl = instl->next;
00739   }
00740 
00741   /* Merge all other trees */
00742   while( !done ) {
00743     base  = NULL;
00744     instl = db_list[curr_db]->inst_head;
00745     while( instl != NULL ) {
00746       if( strcmp( instl->inst->name, "$root" ) != 0 ) {
00747         if( !instl->ignore && !instl->base ) {
00748           if( base == NULL ) {
00749             base        = instl->inst;
00750             instl->base = TRUE;
00751           } else {
00752             instl->ignore = instance_merge_two_trees( base, instl->inst );
00753           }
00754         }
00755       }
00756       instl = instl->next;
00757     }
00758     done = (base == NULL);
00759   }
00760 
00761   PROFILE_END;
00762 
00763 }

void db_output_dumpvars FILE *  vfile  ) 
 

Outputs all needed signals in $dumpvars calls to the specified file.

Outputs all signals that need to be dumped to the given files.

Parameters:
vfile  Pointer to file to output dumpvars output to

00977   { PROFILE(DB_OUTPUT_DUMPVARS);
00978 
00979   inst_link* instl = db_list[curr_db]->inst_head;
00980 
00981   while( instl != NULL ) {
00982     instance_output_dumpvars( vfile, instl->inst );
00983     instl = instl->next;
00984   }
00985 
00986   PROFILE_END;
00987 
00988 }

statement* db_parallelize_statement statement stmt  ) 
 

Checks specified statement for parallelization and if it must be, creates a parallel statement block.

Returns:
Returns pointer to parallelized statement block
Exceptions:
anonymous db_create_statement Throw db_create_expression
Parameters:
stmt  Pointer to statement to check for parallelization

02238   { PROFILE(DB_PARALLELIZE_STATEMENT);
02239 
02240   expression* exp;         /* Expression containing FORK statement */
02241   char*       scope;       /* Name of current parallelized statement scope */
02242 
02243   /* If we are a parallel statement, create a FORK statement for this statement block */
02244   if( (stmt != NULL) && (fork_depth != -1) && (fork_block_depth[fork_depth] == block_depth) ) {
02245 
02246 #ifdef DEBUG_MODE
02247     if( debug_mode ) {
02248       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_parallelize_statement, id: %d, %s, line: %d, fork_depth: %d, block_depth: %d, fork_block_depth: %d",
02249                                   stmt->exp->id, expression_string_op( stmt->exp->op ), stmt->exp->line, fork_depth, block_depth, fork_block_depth[fork_depth] );
02250       assert( rv < USER_MSG_LENGTH );
02251       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02252     }
02253 #endif
02254 
02255     /* Create FORK expression */
02256     exp = db_create_expression( NULL, NULL, EXP_OP_FORK, FALSE, stmt->exp->line, ((stmt->exp->col & 0xffff0000) >> 16), (stmt->exp->col & 0xffff), NULL );
02257 
02258     /* Create unnamed scope */
02259     scope = db_create_unnamed_scope();
02260     if( db_add_function_task_namedblock( FUNIT_NAMED_BLOCK, scope, curr_funit->filename, stmt->exp->line ) ) {
02261 
02262       /* Create a thread block for this statement block */
02263       stmt->suppl.part.head      = 1;
02264       stmt->suppl.part.is_called = 1;
02265       db_add_statement( stmt, stmt );
02266 
02267       /* Bind the FORK expression now */
02268       exp->elem.funit      = curr_funit;
02269       exp->suppl.part.type = ETYPE_FUNIT;
02270       exp->name            = strdup_safe( scope );
02271 
02272       /* Restore the original functional unit */
02273       db_end_function_task_namedblock( stmt->exp->line );
02274 
02275     }
02276     free_safe( scope, (strlen( scope ) + 1) );
02277 
02278     /* Reduce fork and block depth for the new statement */
02279     fork_depth--;
02280     block_depth--;
02281 
02282     Try {
02283 
02284       /* Create FORK statement and add the expression */
02285       stmt = db_create_statement( exp, stmt->ppline );
02286 
02287     } Catch_anonymous {
02288       expression_dealloc( exp, FALSE );
02289       Throw 0;
02290     }
02291 
02292     /* Restore fork and block depth values for parser */
02293     fork_depth++;
02294     block_depth++;
02295 
02296   }
02297 
02298   PROFILE_END;
02299 
02300   return( stmt );
02301 
02302 }

void db_parse_attribute attr_param ap  ) 
 

Parses the specified attribute parameter list for Covered attributes.

Exceptions:
anonymous attribute_parse Throw
Calls the attribute_parse() function and deallocates this list.
Parameters:
ap  Pointer to attribute parameter list to parse

02746   { PROFILE(DB_PARSE_ATTRIBUTE);
02747 
02748 #ifdef DEBUG_MODE
02749   if( debug_mode ) {
02750     print_output( "In db_parse_attribute", DEBUG, __FILE__, __LINE__ );
02751   }
02752 #endif
02753 
02754   Try {
02755 
02756     /* First, parse the entire attribute */
02757     attribute_parse( ap, curr_funit, (exclude_mode > 0) );
02758 
02759   } Catch_anonymous {
02760     attribute_dealloc( ap );
02761     Throw 0;
02762   }
02763 
02764   /* Then deallocate the structure */
02765   attribute_dealloc( ap );
02766 
02767   PROFILE_END;
02768 
02769 }

void db_read const char *  file,
int  read_mode
 

Reads contents of database file and stores into internal lists.

Exceptions:
anonymous info_db_read args_db_read Throw Throw Throw expression_db_read fsm_db_read race_db_read funit_db_read vsignal_db_read funit_db_merge funit_db_merge statement_db_read
Opens specified database file for reading. Reads in each line from the file examining its contents and creating the appropriate type to store the specified information and stores it into the appropriate internal list.
Parameters:
file  Name of database file to read contents from
read_mode  Specifies what to do with read data (see Modes for reading database file for legal values)

00407   { PROFILE(DB_READ);
00408 
00409   FILE*        db_handle;            /* Pointer to database file being read */
00410   int          type;                 /* Specifies object type */
00411   func_unit    tmpfunit;             /* Temporary functional unit pointer */
00412   char*        curr_line;            /* Pointer to current line being read from db */
00413   unsigned int curr_line_size;       /* Allocated number of bytes for curr_line */
00414   char*        rest_line;            /* Pointer to rest of the current line */
00415   int          chars_read;           /* Number of characters currently read on line */
00416   char         parent_scope[4096];   /* Scope of parent functional unit to the current instance */
00417   char         back[4096];           /* Current functional unit instance name */
00418   char         funit_scope[4096];    /* Current scope of functional unit instance */
00419   char         funit_name[256];      /* Current name of functional unit instance */
00420   char         funit_file[4096];     /* Current filename of functional unit instance */
00421   funit_link*  foundfunit;           /* Found functional unit link */
00422   funit_inst*  foundinst;            /* Found functional unit instance */
00423   bool         merge_mode = FALSE;   /* If TRUE, we should currently be merging data */
00424   func_unit*   parent_mod;           /* Pointer to parent module of this functional unit */
00425   bool         inst_name_diff;       /* Specifies the read value of the name diff for the current instance */
00426 
00427 #ifdef DEBUG_MODE
00428   if( debug_mode ) {
00429     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_read, file: %s, mode: %d", obf_file( file ), read_mode );
00430     assert( rv < USER_MSG_LENGTH );
00431     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00432   }
00433 #endif
00434 
00435   /* Setup temporary module for storage */
00436   tmpfunit.name     = funit_name;
00437   tmpfunit.filename = funit_file;
00438 
00439   curr_funit  = NULL;
00440 
00441   if( (db_handle = fopen( file, "r" )) != NULL ) {
00442 
00443     unsigned int rv;
00444 
00445     Try {
00446 
00447       while( util_readline( db_handle, &curr_line, &curr_line_size ) ) {
00448 
00449         Try {
00450 
00451           if( sscanf( curr_line, "%d%n", &type, &chars_read ) == 1 ) {
00452 
00453             rest_line = curr_line + chars_read;
00454 
00455             if( type == DB_TYPE_INFO ) {
00456           
00457               (void)db_create();
00458 
00459               /* Parse rest of line for general info */
00460               info_db_read( &rest_line );
00461   
00462               /* If we are in report mode and this CDD file has not been written bow out now */
00463               if( (info_suppl.part.scored == 0) && 
00464                   ((read_mode == READ_MODE_REPORT_NO_MERGE) ||
00465                    (read_mode == READ_MODE_REPORT_MOD_MERGE)) ) {
00466                 print_output( "Attempting to generate report on non-scored design.  Not supported.", FATAL, __FILE__, __LINE__ );
00467                 Throw 0;
00468               }
00469           
00470             } else if( type == DB_TYPE_SCORE_ARGS ) {
00471           
00472               assert( !merge_mode );
00473          
00474               /* Parse rest of line for argument info (if we are not instance merging) */
00475               if( read_mode != READ_MODE_MERGE_INST_MERGE ) {
00476                 args_db_read( &rest_line );
00477               }
00478             
00479             } else if( type == DB_TYPE_MESSAGE ) {
00480  
00481               assert( !merge_mode );
00482  
00483               /* Parse rest of line for user-supplied message */
00484               if( (read_mode != READ_MODE_MERGE_NO_MERGE) && (read_mode != READ_MODE_MERGE_INST_MERGE) ) {
00485                 message_db_read( &rest_line );
00486               }
00487 
00488             } else if( type == DB_TYPE_MERGED_CDD ) {
00489 
00490               assert( !merge_mode );
00491 
00492               /* Parse rest of line for merged CDD information */
00493               merged_cdd_db_read( &rest_line );
00494     
00495             } else if( type == DB_TYPE_SIGNAL ) {
00496   
00497               assert( !merge_mode );
00498 
00499               /* Parse rest of line for signal info */
00500               vsignal_db_read( &rest_line, curr_funit );
00501  
00502             } else if( type == DB_TYPE_EXPRESSION ) {
00503 
00504               assert( !merge_mode );
00505 
00506               /* Parse rest of line for expression info */
00507               expression_db_read( &rest_line, curr_funit, (read_mode == READ_MODE_NO_MERGE) );
00508   
00509             } else if( type == DB_TYPE_STATEMENT ) {
00510 
00511               assert( !merge_mode );
00512 
00513               /* Parse rest of line for statement info */
00514               statement_db_read( &rest_line, curr_funit, read_mode );
00515 
00516             } else if( type == DB_TYPE_FSM ) {
00517 
00518               assert( !merge_mode );
00519 
00520               /* Parse rest of line for FSM info */
00521               fsm_db_read( &rest_line, curr_funit );
00522 
00523             } else if( type == DB_TYPE_EXCLUDE ) {
00524 
00525               /* Parse rest of line for exclude info */
00526               if( merge_mode ) {
00527                 exclude_db_merge( curr_funit, &rest_line );
00528               } else {
00529                 exclude_db_read( &rest_line, curr_funit );
00530               }
00531 
00532             } else if( type == DB_TYPE_RACE ) {
00533 
00534               assert( !merge_mode );
00535 
00536               /* Parse rest of line for race condition block info */
00537               race_db_read( &rest_line, curr_funit );
00538 
00539             } else if( type == DB_TYPE_FUNIT_VERSION ) {
00540 
00541               assert( !merge_mode );
00542   
00543               /* Parse rest of line for functional unit version information */
00544               funit_version_db_read( curr_funit, &rest_line );
00545 
00546             } else if( (type == DB_TYPE_FUNIT ) || (type == DB_TYPE_INST_ONLY) ) {
00547 
00548               /* Finish handling last functional unit read from CDD file */
00549               if( curr_funit != NULL ) {
00550               
00551                 if( (read_mode != READ_MODE_MERGE_INST_MERGE) || !merge_mode ) {
00552 
00553                   /* Get the scope of the parent module */
00554                   scope_extract_back( funit_scope, back, parent_scope );
00555 
00556                   /* Attempt to add it to the last instance tree */
00557                   if( (db_list[curr_db]->inst_tail == NULL) ||
00558                       !instance_read_add( &(db_list[curr_db]->inst_tail->inst), parent_scope, curr_funit, back ) ) {
00559                     (void)inst_link_add( instance_create( curr_funit, funit_scope, inst_name_diff, FALSE, FALSE, NULL ), &(db_list[curr_db]->inst_head), &(db_list[curr_db]->inst_tail) );
00560                   }
00561 
00562                 }
00563 
00564                 /* If the current functional unit is a merged unit, don't add it to the funit list again */
00565                 if( !merge_mode ) {
00566                   funit_link_add( curr_funit, &(db_list[curr_db]->funit_head), &(db_list[curr_db]->funit_tail) );
00567                 }
00568 
00569               }
00570 
00571               if( type == DB_TYPE_INST_ONLY ) {
00572 
00573                 /* Parse rest of the line for an instance-only structure */
00574                 if( !merge_mode ) {
00575                   instance_only_db_read( &rest_line );
00576                 } else {
00577                   instance_only_db_merge( &rest_line );
00578                 }
00579 
00580                 /* Specify that the current functional unit does not exist */
00581                 curr_funit = NULL;
00582 
00583               } else {
00584 
00585                 /* Reset merge mode */
00586                 merge_mode = FALSE;
00587 
00588                 /* Now finish reading functional unit line */
00589                 funit_db_read( &tmpfunit, funit_scope, &inst_name_diff, &rest_line );
00590                 if( (read_mode == READ_MODE_MERGE_INST_MERGE) &&
00591                     ((foundinst = inst_link_find_by_scope( funit_scope, db_list[curr_db]->inst_head )) != NULL) ) {
00592                   merge_mode = TRUE;
00593                   curr_funit = foundinst->funit;
00594                   funit_db_merge( foundinst->funit, db_handle, TRUE );
00595                 } else if( (read_mode == READ_MODE_REPORT_MOD_MERGE) &&
00596                            ((foundfunit = funit_link_find( tmpfunit.name, tmpfunit.type, db_list[curr_db]->funit_head )) != NULL) ) {
00597                   merge_mode = TRUE;
00598                   curr_funit = foundfunit->funit;
00599                   funit_db_merge( foundfunit->funit, db_handle, FALSE );
00600                 } else {
00601                   curr_funit             = funit_create();
00602                   curr_funit->name       = strdup_safe( funit_name );
00603                   curr_funit->type       = tmpfunit.type;
00604                   curr_funit->filename   = strdup_safe( funit_file );
00605                   curr_funit->start_line = tmpfunit.start_line;
00606                   curr_funit->end_line   = tmpfunit.end_line;
00607                   curr_funit->timescale  = tmpfunit.timescale;
00608                   if( tmpfunit.type != FUNIT_MODULE ) {
00609                     curr_funit->parent = scope_get_parent_funit( db_list[curr_db]->inst_tail->inst, funit_scope );
00610                     parent_mod         = scope_get_parent_module( db_list[curr_db]->inst_tail->inst, funit_scope );
00611                     funit_link_add( curr_funit, &(parent_mod->tf_head), &(parent_mod->tf_tail) );
00612                   }
00613                 }
00614   
00615                 /* Set global functional unit, if it has been found */
00616                 if( (curr_funit != NULL) && (strncmp( curr_funit->name, "$root", 5 ) == 0) ) {
00617                   global_funit = curr_funit;
00618                 }
00619 
00620               }
00621 
00622             } else {
00623 
00624               unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unexpected type %d when parsing database file %s", type, obf_file( file ) );
00625               assert( rv < USER_MSG_LENGTH );
00626               print_output( user_msg, FATAL, __FILE__, __LINE__ );
00627               Throw 0;
00628 
00629             }
00630 
00631           } else {
00632 
00633             unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unexpected line in database file %s", obf_file( file ) );
00634             assert( rv < USER_MSG_LENGTH );
00635             print_output( user_msg, FATAL, __FILE__, __LINE__ );
00636             Throw 0;
00637 
00638           }
00639 
00640         } Catch_anonymous {
00641 
00642           free_safe( curr_line, curr_line_size );
00643           if( (read_mode != READ_MODE_MERGE_INST_MERGE) && (read_mode != READ_MODE_REPORT_MOD_MERGE) ) {
00644             funit_dealloc( curr_funit );
00645           }
00646           Throw 0;
00647 
00648         }
00649 
00650         free_safe( curr_line, curr_line_size );
00651 
00652       }
00653 
00654     } Catch_anonymous {
00655 
00656       unsigned int rv = fclose( db_handle );
00657       assert( rv == 0 );
00658       Throw 0;
00659 
00660     }
00661  
00662     rv = fclose( db_handle );
00663     assert( rv == 0 );
00664 
00665   } else {
00666 
00667     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Could not open %s for reading", obf_file( file ) );
00668     assert( rv < USER_MSG_LENGTH );
00669     print_output( user_msg, FATAL, __FILE__, __LINE__ );
00670     Throw 0;
00671 
00672   }
00673 
00674   /* If the last functional unit was being read, add it now */
00675   if( curr_funit != NULL ) {
00676 
00677     if( (read_mode != READ_MODE_MERGE_INST_MERGE) || !merge_mode ) {
00678 
00679       /* Get the scope of the parent module */
00680       scope_extract_back( funit_scope, back, parent_scope );
00681 
00682       /* Attempt to add it to the last instance tree */
00683       if( (db_list[curr_db]->inst_tail == NULL) ||
00684           !instance_read_add( &(db_list[curr_db]->inst_tail->inst), parent_scope, curr_funit, back ) ) {
00685         (void)inst_link_add( instance_create( curr_funit, funit_scope, inst_name_diff, FALSE, FALSE, NULL ), &(db_list[curr_db]->inst_head), &(db_list[curr_db]->inst_tail) );
00686       }
00687 
00688     }
00689 
00690     /* If the current functional unit was being merged, don't add it to the functional unit list again */
00691     if( !merge_mode ) {
00692       funit_link_add( curr_funit, &(db_list[curr_db]->funit_head), &(db_list[curr_db]->funit_tail) );
00693     }
00694 
00695     curr_funit = NULL;
00696 
00697   }
00698 
00699 #ifdef DEBUG_MODE
00700   /* Display the instance trees, if we are debugging */
00701   if( debug_mode && (db_list != NULL) ) {
00702     inst_link_display( db_list[curr_db]->inst_head );
00703     printf( "-----------------------------------\n" );
00704   }
00705 #endif
00706 
00707   /* Check to make sure that the CDD file contained valid information */
00708   if( (db_size == 0) || (db_list[0]->inst_head == NULL) ) {
00709     print_output( "CDD file was found to be empty", FATAL, __FILE__, __LINE__ );
00710     Throw 0;
00711   }
00712 
00713   PROFILE_END;
00714 
00715 }

void db_remove_statement statement stmt  ) 
 

Removes specified statement and associated expression from list and memory.

Removes specified statement expression and its tree from current module expression list and deallocates both the expression and statement from heap memory. Called when a statement structure is found to contain a statement that is not supported by Covered.

Parameters:
stmt  Pointer to statement to remove from memory

02472   { PROFILE(DB_REMOVE_STATEMENT);
02473 
02474   if( stmt != NULL ) {
02475 
02476 #ifdef DEBUG_MODE
02477     if( debug_mode ) {
02478       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_remove_statement, stmt id: %d, line: %d", 
02479                                   stmt->exp->id, stmt->exp->line );
02480       assert( rv < USER_MSG_LENGTH );
02481       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02482     }
02483 #endif
02484 
02485     /* Call the recursive statement deallocation function */
02486     statement_dealloc_recursive( stmt, TRUE );
02487 
02488   }
02489 
02490   PROFILE_END;
02491 
02492 }

void db_remove_statement_from_current_funit statement stmt  ) 
 

Removes specified statement from current functional unit.

Removes specified statement expression from the current functional unit. Called by statement_dealloc_recursive in statement.c in its deallocation algorithm.

Parameters:
stmt  Pointer to statement to remove from memory

02427   { PROFILE(DB_REMOVE_STATEMENT_FROM_CURRENT_FUNIT);
02428 
02429   inst_link* instl;  /* Pointer to current functional unit instance */
02430 
02431   if( (stmt != NULL) && (stmt->exp != NULL) ) {
02432 
02433 #ifdef DEBUG_MODE
02434     if( debug_mode ) {
02435       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_remove_statement_from_current_funit %s, stmt id: %d, %s, line: %d",
02436                                   obf_funit( curr_funit->name ), stmt->exp->id, expression_string_op( stmt->exp->op ), stmt->exp->line );
02437       assert( rv < USER_MSG_LENGTH );
02438       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02439     }
02440 #endif
02441 
02442     /*
02443      Get a list of all parameters within the given statement expression tree and remove them from
02444      an instance and module parameters.
02445     */
02446     instl = db_list[curr_db]->inst_head;
02447     while( instl != NULL ) {
02448       instance_remove_parms_with_expr( instl->inst, stmt );
02449       instl = instl->next;
02450     }
02451 
02452     /* Remove expression from current module expression list and delete expressions */
02453     exp_link_remove( stmt->exp, &(curr_funit->exp_head), &(curr_funit->exp_tail), TRUE );
02454 
02455     /* Remove this statement link from the current module's stmt_link list */
02456     stmt_link_unlink( stmt, &(curr_funit->stmt_head), &(curr_funit->stmt_tail) );
02457 
02458   }
02459 
02460   PROFILE_END;
02461 
02462 }

void db_remove_stmt_blks_calling_statement statement stmt  ) 
 

Searches entire design for expressions that call the specified statement.

Returns:
Returns a pointer to a list of all expressions found that call the specified statement. Returns NULL if no expressions were found in the design that match this statement.
Searches the list of all expressions in all functional units that call the specified statement and returns these in a list format to the calling function. This function should only be called after the entire design has been parsed to be completely correct.
Parameters:
stmt  Pointer to statement to compare with all expressions

02784   { PROFILE(DB_REMOVE_STMT_BLKS_CALLING_STATEMENT);
02785 
02786   inst_link* instl;  /* Pointer to current instance */ 
02787 
02788   assert( stmt != NULL );
02789 
02790   instl = db_list[curr_db]->inst_head;
02791   while( instl != NULL ) {
02792     instance_remove_stmt_blks_calling_stmt( instl->inst, stmt );
02793     instl = instl->next;
02794   }
02795 
02796   PROFILE_END;
02797 
02798 }

uint64 db_scale_to_precision uint64  value,
func_unit funit
 

Returns a scaled version of the given value to the timescale for the given functional unit.

Returns:
Returns scaled version of input value.
Takes in specified delay value and scales it to the correct timescale for the given module.
Parameters:
value  Delay value to scale
funit  Pointer to current functional unit of expression to scale

00774   { PROFILE(DB_SCALE_TO_PRECISION);
00775 
00776   int units = funit->ts_unit;
00777 
00778   assert( units >= global_timescale_precision );
00779 
00780   while( units > global_timescale_precision ) {
00781     units--;
00782     value *= (uint64)10;
00783   }
00784 
00785   PROFILE_END;
00786 
00787   return( value );
00788 
00789 }

void db_set_symbol_char const char *  sym,
char  value
 

Sets the found symbol value to specified character value. Called by VCD lexer.

Searches the timestep symtable followed by the VCD symbol table searching for the symbol that matches the specified argument. Once a symbol is found, its value parameter is set to the specified character. If the symbol was found in the VCD symbol table, it is copied to the timestep symbol table.

Parameters:
sym  Name of symbol to set character value to
value  String version of value to set symbol table entry to

02998   { PROFILE(DB_SET_SYMBOL_CHAR);
02999 
03000   char val[2];  /* Value to store */
03001 
03002 #ifdef DEBUG_MODE
03003   if( debug_mode ) {
03004     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_set_symbol_char, sym: %s, value: %c", sym, value );
03005     assert( rv < USER_MSG_LENGTH );
03006     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
03007   }
03008 #endif
03009 
03010   /* Put together value string */
03011   val[0] = value;
03012   val[1] = '\0';
03013 
03014   /* Set value of all matching occurrences in current timestep. */
03015   symtable_set_value( sym, val );
03016 
03017   PROFILE_END;
03018 
03019 }

void db_set_symbol_string const char *  sym,
const char *  value
 

Sets the found symbol value to specified string value. Called by VCD lexer.

Searches the timestep symtable followed by the VCD symbol table searching for the symbol that matches the specified argument. Once a symbol is found, its value parameter is set to the specified string. If the symbol was found in the VCD symbol table, it is copied to the timestep symbol table.

Parameters:
sym  Name of symbol to set character value to
value  String version of value to set symbol table entry to

03030   { PROFILE(DB_SET_SYMBOL_STRING);
03031 
03032 #ifdef DEBUG_MODE
03033   if( debug_mode ) {
03034     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_set_symbol_string, sym: %s, value: %s", sym, value );
03035     assert( rv < USER_MSG_LENGTH );
03036     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
03037   }
03038 #endif
03039 
03040   /* Set value of all matching occurrences in current timestep. */
03041   symtable_set_value( sym, value );
03042 
03043   PROFILE_END;
03044 
03045 }

void db_set_timescale int  unit,
int  precision
 

Sets the global timescale unit and precision variables.

Sets the global timescale unit and precision variables.

Parameters:
unit  Timescale unit offset value
precision  Timescale precision offset value

00833   { PROFILE(DB_SET_TIMESCALE);
00834 
00835   current_timescale_unit = unit;
00836 
00837   /* Set the global precision value to the lowest precision value specified */
00838   if( precision < global_timescale_precision ) {
00839     global_timescale_precision = precision;
00840   }
00841 
00842   PROFILE_END;
00843 
00844 }

void db_set_vcd_scope const char *  scope  ) 
 

Sets current VCD scope to specified scope.

Sets the curr_inst_scope global variable to the specified scope.

Parameters:
scope  Current VCD scope

02874   { PROFILE(DB_SET_VCD_SCOPE);
02875 
02876 #ifdef DEBUG_MODE
02877   if( debug_mode ) {
02878     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_set_vcd_scope, scope: %s", obf_inst( scope ) );
02879     assert( rv < USER_MSG_LENGTH );
02880     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02881   }
02882 #endif
02883 
02884   assert( scope != NULL );
02885 
02886   /* Create a new scope item */
02887   curr_inst_scope = (char**)realloc_safe( curr_inst_scope, (sizeof( char* ) * curr_inst_scope_size), (sizeof( char* ) * (curr_inst_scope_size + 1)) );
02888   curr_inst_scope[curr_inst_scope_size] = strdup_safe( scope );
02889   curr_inst_scope_size++;
02890 
02891   /* Synchronize the current instance to the value of curr_inst_scope */
02892   db_sync_curr_instance();
02893 
02894   PROFILE_END;
02895 
02896 }

bool db_statement_connect statement curr_stmt,
statement next_stmt
 

Connects one statement block to another.

Returns:
Returns TRUE if statement was properly connected to the given statement list; otherwise, returns FALSE.
Calls the statement_connect function located in statement.c with the specified parameters. If the statement connection was not achieved, displays warning to user and returns FALSE. The calling function should throw this statement away.
Parameters:
curr_stmt  Pointer to current statement to attach
next_stmt  Pointer to next statement to attach to

02656   { PROFILE(DB_STATEMENT_CONNECT);
02657 
02658   bool retval;  /* Return value for this function */
02659 
02660 #ifdef DEBUG_MODE
02661   if( debug_mode ) {
02662     int          curr_id;  /* Current statement ID */
02663     int          next_id;  /* Next statement ID */
02664     unsigned int rv;
02665 
02666     if( curr_stmt == NULL ) {
02667       curr_id = 0;
02668     } else {
02669       curr_id = curr_stmt->exp->id;
02670     }
02671 
02672     if( next_stmt == NULL ) {
02673       next_id = 0;
02674     } else {
02675       next_id = next_stmt->exp->id;
02676     }
02677 
02678     rv = snprintf( user_msg, USER_MSG_LENGTH, "In db_statement_connect, curr_stmt: %d, next_stmt: %d", curr_id, next_id );
02679     assert( rv < USER_MSG_LENGTH );
02680     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02681   }
02682 #endif
02683 
02684   /*
02685    Connect statement, if it was not successful, add it to the functional unit's statement list immediately
02686    as it will not be later on.
02687   */
02688   if( !(retval = statement_connect( curr_stmt, next_stmt, stmt_conn_id )) ) {
02689 
02690     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unreachable statement found starting at line %d in file %s.  Ignoring...",
02691                                 next_stmt->exp->line, obf_file( curr_funit->filename ) );
02692     assert( rv < USER_MSG_LENGTH );
02693     print_output( user_msg, WARNING, __FILE__, __LINE__ );
02694 
02695   }
02696 
02697   /* Increment stmt_conn_id for next statement connection */
02698   stmt_conn_id++;
02699 
02700   PROFILE_END;
02701 
02702   return( retval );
02703 
02704 }

void db_sync_curr_instance  ) 
 

Synchronizes the curr_instance pointer to match the curr_inst_scope hierarchy.

Synchronizes the curr_instance pointer to match the curr_inst_scope hierarchy.

02837                              { PROFILE(DB_SYNC_CURR_INSTANCE);
02838  
02839   char  stripped_scope[4096];  /* Temporary string */
02840   char* scope;                 /* Current instance scope string */
02841 
02842   assert( db_list[curr_db]->leading_hier_num > 0 );
02843 
02844   if( (scope = db_gen_curr_inst_scope()) != NULL ) {
02845 
02846     if( scope[0] != '\0' ) {
02847 
02848       curr_instance = inst_link_find_by_scope( scope, db_list[curr_db]->inst_head );
02849 
02850       /* If we have found at least one matching instance, set the one_instance_found flag */
02851       if( curr_instance != NULL ) {
02852         one_instance_found = TRUE;
02853       }
02854 
02855     }
02856 
02857     free_safe( scope, (strlen( scope ) + 1) );
02858 
02859   } else {
02860 
02861     curr_instance = NULL;
02862 
02863   }
02864 
02865   PROFILE_END;
02866 
02867 } 

void db_vcd_upscope  ) 
 

Moves current VCD hierarchy up one level.

Moves the curr_inst_scope up one level of hierarchy. This function is called when the $upscope keyword is seen in a VCD file.

02902                       { PROFILE(DB_VCD_UPSCOPE);
02903 
02904 #ifdef DEBUG_MODE
02905   if( debug_mode ) {
02906     char*        scope = db_gen_curr_inst_scope();
02907     unsigned int rv    = snprintf( user_msg, USER_MSG_LENGTH, "In db_vcd_upscope, curr_inst_scope: %s", obf_inst( scope ) );
02908     assert( rv < USER_MSG_LENGTH );
02909     print_output( user_msg, DEBUG, __FILE__, __LINE__ );
02910     free_safe( scope, (strlen( scope ) + 1) );
02911   }
02912 #endif
02913 
02914   /* Deallocate the last scope item */
02915   if( curr_inst_scope_size > 0 ) {
02916 
02917     curr_inst_scope_size--;
02918     free_safe( curr_inst_scope[curr_inst_scope_size], (strlen( curr_inst_scope[curr_inst_scope_size] ) + 1) );
02919     curr_inst_scope = (char**)realloc_safe( curr_inst_scope, (sizeof( char* ) * (curr_inst_scope_size + 1)), (sizeof( char* ) * curr_inst_scope_size) );
02920 
02921     db_sync_curr_instance();
02922 
02923   }
02924 
02925   PROFILE_END;
02926 
02927 }

void db_write const char *  file,
bool  parse_mode,
bool  issue_ids,
bool  report_save
 

Writes contents of expressions, functional units and vsignals to database file.

Exceptions:
anonymous Throw Throw instance_db_write
Opens specified database for writing. If database open successful, iterates through functional unit, expression and signal lists, displaying each to the database file. If database write successful, returns TRUE; otherwise, returns FALSE to the calling function.
Parameters:
file  Name of database file to output contents to
parse_mode  Specifies if we are outputting parse data or score data
issue_ids  Specifies if we need to issue/reissue expression and signal IDs
report_save  Specifies if we are attempting to "save" a CDD file modified in the report command

00341   { PROFILE(DB_WRITE);
00342 
00343   FILE*      db_handle;  /* Pointer to database file being written */
00344   inst_link* instl;      /* Pointer to current instance link */
00345 
00346   if( (db_handle = fopen( file, "w" )) != NULL ) {
00347 
00348     unsigned int rv;
00349 
00350     Try {
00351 
00352       /* Reset expression IDs */
00353       curr_expr_id = 1;
00354 
00355       /* Iterate through instance tree */
00356       assert( db_list[curr_db]->inst_head != NULL );
00357       info_db_write( db_handle );
00358 
00359       instl = db_list[curr_db]->inst_head;
00360       while( instl != NULL ) {
00361 
00362         /* Only output the given instance tree if it is not ignored */
00363         if( !instl->ignore ) {
00364 
00365           /* Now write the instance */
00366           instance_db_write( instl->inst, db_handle, instl->inst->name, parse_mode, issue_ids, report_save );
00367 
00368         }
00369 
00370         instl = instl->next;
00371 
00372       }
00373 
00374     } Catch_anonymous {
00375       rv = fclose( db_handle );
00376       assert( rv == 0 );
00377       Throw 0;
00378     }
00379 
00380     rv = fclose( db_handle );
00381     assert( rv == 0 );
00382 
00383   } else {
00384 
00385     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Could not open %s for writing", obf_file( file ) );
00386     assert( rv < USER_MSG_LENGTH );
00387     print_output( user_msg, FATAL, __FILE__, __LINE__ );
00388     Throw 0;
00389 
00390   }
00391 
00392   PROFILE_END;
00393 
00394 }


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