#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_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. | |
| fsm_var * | fsm_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_unit * | curr_funit |
| fsm_var * | fsm_var_head = NULL |
| fsm_var * | fsm_var_tail = NULL |
| fv_bind * | fsm_var_bind_head = NULL |
| fv_bind * | fsm_var_bind_tail = NULL |
| fv_bind * | fsm_var_stmt_head = NULL |
| fv_bind * | fsm_var_stmt_tail = NULL |
|
||||||||||||||||||||||||
|
Allocates, initializes and adds FSM variable to global list.
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 }
|
|
||||||||||||
|
Iterates through specified expression tree, adding each expression to the specified functional unit if the expression does not already exist in the functional unit.
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 }
|
|
|
Performs FSM signal/expression binding process.
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 }
|
|
||||||||||||||||
|
Adds specified signal and expression to binding list.
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
Deallocates an FSM variable entry from memory.
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 }
|
|
|
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 }
|
|
|
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.
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 }
|
|
||||||||||||
|
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.
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 }
|
|
|
Index of current database in db_list array that is being handled. |
|
|
Pointer to the functional unit structure for the functional unit that is currently being parsed. |
|
|
Array of database pointers storing all currently loaded databases. |
|
|
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. |
|
|
Pointer to the tail of the list of FSM variable bindings. |
|
|
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. |
|
|
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. |
|
|
Pointer to the tail of the list of FSM statement/functional unit bindings. |
|
|
Pointer to the tail of the list of FSM scopes in the design. |
|
|
Holds some output that will be displayed via the print_output command. This is created globally so that memory does not need to be reallocated for each function that wishes to use it. |
1.3.4