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

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


Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
10/3/2003

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "binding.h"
#include "codegen.h"
#include "db.h"
#include "defines.h"
#include "expr.h"
#include "fsm.h"
#include "fsm_var.h"
#include "link.h"
#include "obfuscate.h"
#include "statement.h"
#include "util.h"

Functions

void fsm_var_remove (fsm_var *)
fsm_varfsm_var_add (const char *funit_name, expression *in_state, expression *out_state, char *name, bool exclude)
 Allocates, initializes and adds FSM variable to global list.

fsm_varfsm_var_is_output_state (expression *expr)
void fsm_var_bind_expr (char *sig_name, expression *expr, char *funit_name)
void fsm_var_add_expr (expression *expr, func_unit *funit)
bool fsm_var_bind_stmt (statement *stmt, const char *funit_name)
void fsm_var_bind_add (char *sig_name, expression *expr, char *funit_name)
 Adds specified signal and expression to binding list.

void fsm_var_stmt_add (statement *stmt, char *funit_name)
 Add specified functional unit and statement to binding list.

void fsm_var_bind ()
 Performs FSM signal/expression binding process.

void fsm_var_dealloc (fsm_var *fv)
void fsm_var_cleanup ()
 Cleans up the global lists used in this file.


Variables

char user_msg [USER_MSG_LENGTH]
db ** db_list
unsigned int curr_db
func_unitcurr_funit
fsm_varfsm_var_head = NULL
fsm_varfsm_var_tail = NULL
fv_bindfsm_var_bind_head = NULL
fv_bindfsm_var_bind_tail = NULL
fv_bindfsm_var_stmt_head = NULL
fv_bindfsm_var_stmt_tail = NULL


Function Documentation

fsm_var* fsm_var_add const char *  funit_name,
expression in_state,
expression out_state,
char *  name,
bool  exclude
 

Allocates, initializes and adds FSM variable to global list.

Returns:
Returns pointer to newly allocated FSM variable.
Adds the specified Verilog hierarchical scope to a list of FSM scopes to find during the parsing phase.
Parameters:
funit_name  String containing functional unit containing FSM state variable
in_state  Pointer to expression containing input state
out_state  Pointer to expression containing output state
name  Name of this FSM (only valid for attributes
exclude  If TRUE, excludes the FSM from coverage consideration

00108   { PROFILE(FSM_VAR_ADD);
00109 
00110   fsm_var*    new_var = NULL;  /* Pointer to newly created FSM variable */
00111   funit_link* funitl;          /* Pointer to functional unit link found */
00112   fsm*        table;           /* Pointer to newly create FSM */
00113 
00114   /* If we have not parsed design, add new FSM variable to list */
00115   if( db_list[curr_db]->funit_head == NULL ) {
00116 
00117     new_var          = (fsm_var*)malloc_safe( sizeof( fsm_var ) );
00118     new_var->funit   = strdup_safe( funit_name );
00119     new_var->name    = NULL;
00120     new_var->ivar    = in_state;
00121     new_var->ovar    = out_state;
00122     new_var->iexp    = NULL;
00123     new_var->table   = NULL;
00124     new_var->exclude = exclude;
00125     new_var->next    = NULL;
00126 
00127     if( fsm_var_head == NULL ) {
00128       fsm_var_head = fsm_var_tail = new_var;
00129     } else {
00130       fsm_var_tail->next = new_var;
00131       fsm_var_tail       = new_var;
00132     }
00133 
00134   } else {
00135 
00136     if( (funitl = funit_link_find( funit_name, FUNIT_MODULE, db_list[curr_db]->funit_head )) != NULL ) {
00137       table = fsm_create( in_state, out_state, exclude );
00138       if( name != NULL ) {
00139         table->name = strdup_safe( name );
00140       }
00141       in_state->table  = table;
00142       out_state->table = table;
00143       fsm_link_add( table, &(funitl->funit->fsm_head), &(funitl->funit->fsm_tail) );
00144     } else {
00145       assert( funitl != NULL );
00146     }
00147 
00148   }
00149 
00150   return( new_var );
00151 
00152 }

void fsm_var_add_expr expression expr,
func_unit funit
[static]
 

Iterates through specified expression tree, adding each expression to the specified functional unit if the expression does not already exist in the functional unit.

Parameters:
expr  Pointer to expression to add to the specified functional unit
funit  Pointer to functional unit structure to add expression to

00223   { PROFILE(FSM_VAR_ADD_EXPR);
00224 
00225   if( expr != NULL ) {
00226 
00227     if( exp_link_find( expr->id, funit->exp_head ) == NULL ) {
00228 
00229       /* Set the global curr_funit to the expression's functional unit */
00230       curr_funit = funit;
00231 
00232       /* Add expression's children first. */
00233       db_add_expression( expr->right );
00234       db_add_expression( expr->left );
00235 
00236       /* Now add this expression to the list. */
00237       exp_link_add( expr, &(funit->exp_head), &(funit->exp_tail) );
00238 
00239       /* Now clear the curr_funit */
00240       curr_funit = NULL;
00241 
00242     }
00243 
00244   }
00245 
00246   PROFILE_END;
00247 
00248 }

void fsm_var_bind  ) 
 

Performs FSM signal/expression binding process.

Exceptions:
anonymous fsm_var_bind_expr Throw
After Verilog parsing has completed, this function should be called to bind all signals to their associated FSM state expressions and functional units. For each entry in the FSM binding list the signal name is looked in the functional unit specified in the binding entry. If the signal is found, the associated expression pointer is added to the signal's expression list and the expression's signal pointer is set to point at the found signal structure. If the signal was not found, an error message is reported to the user, specifying the signal did not exist in the design.

After the signals and expressions have been bound, the FSM statement binding list is iterated through binding all statements containing FSM state expressions to the functional unit that it is a part of. If the statement contains an FSM state expression that is an output state expression, create the FSM structure for this FSM and add it to the design.

00392                     { PROFILE(FSM_VAR_BIND);
00393 
00394   fv_bind* curr = NULL;  /* Pointer to current FSM variable */
00395   fv_bind* tmp;          /* Temporary pointer to FSM bind structure */
00396 
00397   Try {
00398 
00399     curr = fsm_var_bind_head;
00400     while( curr != NULL ) {
00401 
00402       /* Perform binding */
00403       fsm_var_bind_expr( curr->sig_name, curr->expr, curr->funit_name );
00404 
00405       tmp = curr->next;
00406 
00407       /* Deallocate memory for this bind structure */
00408       free_safe( curr->sig_name, (strlen( curr->sig_name ) + 1) );
00409       free_safe( curr->funit_name, (strlen( curr->funit_name ) + 1) );
00410       free_safe( curr, sizeof( fv_bind ) );
00411 
00412       curr = tmp;
00413 
00414     }
00415 
00416   } Catch_anonymous {
00417     while( curr != NULL ) {
00418       tmp = curr->next;
00419       free_safe( curr->sig_name, (strlen( curr->sig_name ) + 1) );
00420       free_safe( curr->funit_name, (strlen( curr->funit_name ) + 1) );
00421       free_safe( curr, sizeof( fv_bind ) );
00422       curr = tmp;
00423     } 
00424     curr = fsm_var_stmt_head;
00425     while( curr != NULL ) {
00426       tmp = curr->next;
00427       free_safe( curr->funit_name, (strlen( curr->funit_name ) + 1) );
00428       free_safe( curr, sizeof( fv_bind ) );
00429       curr = tmp;
00430     }
00431     Throw 0;
00432   }
00433 
00434   curr = fsm_var_stmt_head;
00435   while( curr != NULL ) {
00436 
00437     /* Bind statement to functional unit */
00438     (void)fsm_var_bind_stmt( curr->stmt, curr->funit_name );
00439 
00440     tmp = curr->next;
00441 
00442     /* Deallocate memory for this bind structure */
00443     free_safe( curr->funit_name, (strlen( curr->funit_name ) + 1) );
00444     free_safe( curr, sizeof( fv_bind ) );
00445 
00446     curr = tmp;
00447 
00448   }
00449 
00450   PROFILE_END;
00451 
00452 }

void fsm_var_bind_add char *  sig_name,
expression expr,
char *  funit_name
 

Adds specified signal and expression to binding list.

Exceptions:
anonymous fsm_var_bind_expr
Creates a new FSM binding structure and initializes it with the specified information. The FSM binding structure is then added to the global list of FSM binding structures to be bound after parsing is complete.
Parameters:
sig_name  Name of signal to bind
expr  Pointer to expression to bind
funit_name  Name of functional unit that will contain the expression and signal being bound

00317   { PROFILE(FSM_VAR_BIND_ADD);
00318 
00319   fv_bind* fvb;  /* Pointer to new FSM variable binding structure */
00320 
00321   /* If the functional unit list does not exist yet, we need to bind this later; otherwise, bind now */
00322   if( db_list[curr_db]->funit_head == NULL ) {
00323 
00324     /* Allocate and initialize FSM variable bind structure */
00325     fvb             = (fv_bind*)malloc_safe( sizeof( fv_bind ) );
00326     fvb->sig_name   = strdup_safe( sig_name );
00327     fvb->expr       = expr;
00328     fvb->funit_name = strdup_safe( funit_name );
00329     fvb->next       = NULL;
00330 
00331     /* Add new structure to the global list */
00332     if( fsm_var_bind_head == NULL ) {
00333       fsm_var_bind_head = fsm_var_bind_tail = fvb;
00334     } else {
00335       fsm_var_bind_tail->next = fvb;
00336       fsm_var_bind_tail       = fvb;
00337     }
00338 
00339   } else {
00340 
00341     fsm_var_bind_expr( sig_name, expr, funit_name );
00342 
00343   }
00344 
00345   PROFILE_END;
00346 
00347 }

void fsm_var_bind_expr char *  sig_name,
expression expr,
char *  funit_name
[static]
 

Exceptions:
anonymous Throw Throw
Searches the functional unit list for the functional unit called funit_name. If the functional unit is found in the design, searches this functional unit for the signal called sig_name. If the signal is found, the signal and specified expression expr are bound to each other and this function returns a value of TRUE. If the signal name could not be found or the functional unit name could not be found in the design, no binding occurs and the function displays an error message and returns a value of FALSE to the calling function.
Parameters:
sig_name  String name of signal to bind to specified expression
expr  Pointer to expression to bind to signal called sig_name
funit_name  String name of functional unit that contains the expression pointed to by expr

00193   { PROFILE(FSM_VAR_BIND_EXPR);
00194 
00195   funit_link* funitl;  /* Pointer to found functional unit link element */
00196 
00197   if( (funitl = funit_link_find( funit_name, FUNIT_MODULE, db_list[curr_db]->funit_head )) != NULL ) {
00198     if( !bind_signal( sig_name, expr, funitl->funit, TRUE, FALSE, FALSE, expr->line, FALSE ) ) {
00199       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to bind FSM-specified signal (%s) to expression (%d) in module (%s)",
00200                                   obf_sig( sig_name ), expr->id, obf_funit( funit_name ) );
00201       assert( rv < USER_MSG_LENGTH );
00202       print_output( user_msg, FATAL, __FILE__, __LINE__ );
00203       Throw 0;
00204     }
00205   } else {
00206     unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Unable to find FSM-specified module (%s) in design", obf_funit( funit_name ) ); 
00207     assert( rv < USER_MSG_LENGTH );
00208     print_output( user_msg, FATAL, __FILE__, __LINE__ );
00209     Throw 0;
00210   }
00211 
00212   PROFILE_END;
00213 
00214 }

bool fsm_var_bind_stmt statement stmt,
const char *  funit_name
[static]
 

Returns:
Returns a value of TRUE if the statement was successfully bound to the specified functional unit name; otherwise, returns a value of FALSE.
Searches the design functional unit list for a functional unit called funit_name. If the functional unit is found in the design, adds the statement's expression tree to the design, sets the STMT_ADDED bit in the statement's supplemental field, adds this statement to the found functional unit structure, and finally creates an FSM table if the statement contains an output state FSM expression tree and returns a value of TRUE to the calling function. If the functional unit could not be found, this function, returns a value of FALSE to the calling function.
Parameters:
stmt  Pointer to statement to bind
funit_name  String name of functional unit which will contain stmt

00265   { PROFILE(FSM_VAR_BIND_STMT);
00266 
00267   bool        retval = FALSE;  /* Return value for this function */
00268   funit_link* funitl;          /* Pointer to found functional unit link element */
00269   fsm_var*    fv;              /* Pointer to found FSM variable */
00270 
00271   if( (funitl = funit_link_find( funit_name, FUNIT_MODULE, db_list[curr_db]->funit_head )) != NULL ) {
00272 
00273     /* First, add expression tree to found functional unit expression list */
00274     fsm_var_add_expr( stmt->exp, funitl->funit );
00275 
00276     /* Set ADDED bit of this statement */
00277     stmt->suppl.part.added = 1;
00278 
00279     /* Second, add our statement to this functional unit's statement list */
00280     stmt_link_add_head( stmt, &(funitl->funit->stmt_head), &(funitl->funit->stmt_tail) );
00281 
00282     /* Third, add the functional unit to this statement's pointer */
00283     stmt->funit = funitl->funit;
00284 
00285     /* Finally, create the new FSM if we are the output state */
00286     if( (fv = fsm_var_is_output_state( stmt->exp )) != NULL ) {
00287       fv->table       = fsm_create( fv->ivar, fv->ovar, fv->exclude );
00288       fv->ivar->table = fv->table;
00289       fv->ovar->table = fv->table;
00290       fsm_link_add( fv->table, &(funitl->funit->fsm_head), &(funitl->funit->fsm_tail) );
00291       fsm_var_remove( fv );
00292     }
00293 
00294   } else {
00295 
00296     retval = FALSE;
00297 
00298   }
00299 
00300   PROFILE_END;
00301 
00302   return( retval );
00303 
00304 }

void fsm_var_cleanup  ) 
 

Cleans up the global lists used in this file.

Iterates through the various global lists in this file, deallocating all memory. This function is called when an error has occurred during the parsing stage.

00520                        { PROFILE(FSM_VAR_CLEANUP);
00521 
00522   fsm_var* curr_fv;  /* Pointer to the current fsm_var structure */
00523   fsm_var* tmp_fv;   /* Temporary pointer */
00524   fv_bind* curr_fvb = fsm_var_bind_head;  /* Pointer to the current fv_bind structure */ 
00525   fv_bind* tmp_fvb;                       /* Temporary pointer */
00526 
00527   /* Deallocate fsm_var list */
00528   curr_fv = fsm_var_head;
00529   while( curr_fv != NULL ) {
00530     tmp_fv  = curr_fv;
00531     curr_fv = curr_fv->next;
00532 
00533     free_safe( tmp_fv->funit, (strlen( curr_fv->funit ) + 1) );
00534     expression_dealloc( tmp_fv->ivar, FALSE );
00535     expression_dealloc( tmp_fv->ovar, FALSE );
00536     free_safe( tmp_fv, sizeof( fsm_var ) );
00537   }
00538   fsm_var_head = fsm_var_tail = NULL;
00539 
00540   /* Deallocate fsm_var_bind list */
00541   curr_fvb = fsm_var_bind_head;
00542   while( curr_fvb != NULL ) {
00543     tmp_fvb  = curr_fvb;
00544     curr_fvb = curr_fvb->next;
00545 
00546     free_safe( tmp_fvb->sig_name,   (strlen( tmp_fvb->sig_name ) + 1) );
00547     free_safe( tmp_fvb->funit_name, (strlen( tmp_fvb->funit_name ) + 1) );
00548     expression_dealloc( tmp_fvb->expr, FALSE );
00549     free_safe( tmp_fvb, sizeof( fv_bind ) );
00550   }
00551   fsm_var_bind_head = fsm_var_bind_tail = NULL;
00552 
00553   /* Deallocate fsm_var_stmt list */
00554   curr_fvb = fsm_var_stmt_head;
00555   while( curr_fvb != NULL ) {
00556     tmp_fvb  = curr_fvb;
00557     curr_fvb = curr_fvb->next;
00558     
00559     free_safe( tmp_fvb->funit_name, (strlen( tmp_fvb->funit_name ) + 1) );
00560     expression_dealloc( tmp_fvb->stmt->exp, FALSE );
00561     statement_dealloc( tmp_fvb->stmt );
00562     free_safe( tmp_fvb, sizeof( fv_bind ) );
00563   }
00564   fsm_var_stmt_head = fsm_var_stmt_tail = NULL;
00565 
00566   PROFILE_END;
00567 
00568 }

void fsm_var_dealloc fsm_var fv  )  [static]
 

Deallocates an FSM variable entry from memory.

Parameters:
fv  Pointer to FSM variable to deallocate

00459   { PROFILE(FSM_VAR_DEALLOC);
00460 
00461   if( fv != NULL ) {
00462 
00463     /* Deallocate the functional unit name string */
00464     free_safe( fv->funit, (strlen( fv->funit ) + 1) );
00465 
00466     /* Finally, deallocate ourself */
00467     free_safe( fv, sizeof( fsm_var ) );
00468 
00469   }
00470 
00471   PROFILE_END;
00472 
00473 }

fsm_var* fsm_var_is_output_state expression expr  )  [static]
 

Returns:
Returns pointer to found FSM variable that contains this expression as an output expression.
Searches the FSM variable list for the FSM variable that contains the specified expression as its output state expression. If no FSM variable was found, returns a value of NULL to the calling function.
Parameters:
expr  Pointer to expression to evaluate

00164   { PROFILE(FSM_VAR_IS_OUTPUT_STATE);
00165 
00166   fsm_var* curr;  /* Pointer to current FSM variable structure */
00167 
00168   curr = fsm_var_head;
00169   while( (curr != NULL) && (curr->ovar != expr) ) {
00170     curr = curr->next;
00171   }
00172 
00173   PROFILE_END;
00174 
00175   return( curr );
00176 
00177 }

void fsm_var_remove fsm_var fv  )  [static]
 

Searches global FSM variable list for matching FSM variable structure. When match is found, remove the structure and deallocate it from memory being sure to keep the global list intact.

Parameters:
fv  Pointer to FSM variable structure to remove from global list

00482   { PROFILE(FSM_VAR_REMOVE);
00483 
00484   fsm_var* curr;  /* Pointer to current FSM variable structure in list */
00485   fsm_var* last;  /* Pointer to last FSM variable structure evaluated */
00486 
00487   /* Find matching FSM variable structure */
00488   curr = fsm_var_head;
00489   last = NULL;
00490   while( (curr != NULL) && (curr != fv) ) {
00491     last = curr;
00492     curr = curr->next;
00493   }
00494 
00495   /* If a matching FSM variable structure was found, remove it from the global list. */
00496   if( curr != NULL ) {
00497 
00498     if( (curr == fsm_var_head) && (curr == fsm_var_tail) ) {
00499       fsm_var_head = fsm_var_tail = NULL;
00500     } else if( curr == fsm_var_head ) {
00501       fsm_var_head = curr->next;
00502     } else if( curr == fsm_var_tail ) {
00503       fsm_var_tail = last;
00504     } else {
00505       last->next = curr->next;
00506     }
00507 
00508     fsm_var_dealloc( curr );
00509 
00510   }
00511 
00512   PROFILE_END;
00513 
00514 }

void fsm_var_stmt_add statement stmt,
char *  funit_name
 

Add specified functional unit and statement to binding list.

Allocates and initializes an FSM variable binding entry and adds it to the fsm_var_stmt list for later processing.

Parameters:
stmt  Pointer to statement containing FSM state expression
funit_name  Name of functional unit that will contain stmt

00356   { PROFILE(FSM_VAR_STMT_ADD);
00357 
00358   fv_bind* fvb;  /* Pointer to new FSM variable binding structure */
00359 
00360   fvb             = (fv_bind*)malloc_safe( sizeof( fv_bind ) );
00361   fvb->stmt       = stmt;
00362   fvb->funit_name = strdup_safe( funit_name );
00363   fvb->next       = NULL;
00364 
00365   /* Add new structure to the head of the global list */
00366   if( fsm_var_stmt_head == NULL ) {
00367     fsm_var_stmt_head = fsm_var_stmt_tail = fvb;
00368   } else {
00369     fvb->next         = fsm_var_stmt_head;
00370     fsm_var_stmt_head = fvb;
00371   }
00372 
00373   PROFILE_END;
00374 
00375 }


Variable Documentation

unsigned int curr_db
 

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

func_unit* curr_funit
 

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

db** db_list
 

Array of database pointers storing all currently loaded databases.

fv_bind* fsm_var_bind_head = NULL [static]
 

Pointer to the head of the list of FSM variable bindings between signal names and expression pointers. During the command-line parse of FSM variables, bindings will be submitted into this list for processing after Verilog parsing has completed. After Verilog parsing has completed, the FSM bind function needs to be called to bind all FSM signals/expressions to each other.

fv_bind* fsm_var_bind_tail = NULL [static]
 

Pointer to the tail of the list of FSM variable bindings.

fsm_var* fsm_var_head = NULL [static]
 

Pointer to the head of the list of FSM scopes in the design. To extract an FSM, the user must specify the scope to the FSM state variable of the FSM to extract. When the parser finds this signal in the design, the appropriate FSM is created and initialized. As a note, we may make the FSM extraction more automatic (smarter) in the future, but we will always allow the user to make these choices with the -F option to the score command.

fv_bind* fsm_var_stmt_head = NULL [static]
 

Pointer to the head of the list of FSM variable statement/functional unit bindings. During the command-line parse of FSM variables, bindings will be submitted into this list for processing after Verilog parsing has completed. After Verilog parsing has completed, the FSM bind function needs to be called to bind all FSM statements/functional units to each other.

fv_bind* fsm_var_stmt_tail = NULL [static]
 

Pointer to the tail of the list of FSM statement/functional unit bindings.

fsm_var* fsm_var_tail = NULL [static]
 

Pointer to the tail of the list of FSM scopes in the design.

char user_msg[USER_MSG_LENGTH]
 

Holds some output that will be displayed via the print_output command. This is created globally so that memory does not need to be reallocated for each function that wishes to use it.


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