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

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


Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
6/20/2002
The simulation engine is made up of three parts:
  1. pre-simulation statement queue
  2. statement simulation engine
  3. expression simulation engine
The operation of the simulation engine is as follows. When a signal is found in the VCD file, the expressions to which it is a part of the RHS are looked up in the design tree. The expression tree is then parsed from the expression to the root, setting the ESUPPL_IS_LEFT_CHANGED or ESUPPL_IS_RIGHT_CHANGED as it makes its way to the root. When at the root expression, the parent pointer is to the statement that owns the expression tree and its head bit is interrogated. If this bit is a 1, the expression's statement is loaded into the pre-simulation statement queue. If the bit is a 0, no further action is taken.
Once the timestep marker has been set, the simulate function is called. The statement located at the head of the queue is placed into the statement simulation engine and the head pointer is set to point to the next statement in the queue. The head statement is continually taken until the pre-simulation statement queue is empty. This signifies that the timestep has been completed.
When a statement is placed into the statement simulation engine, the head bit is cleared in the root expression. Additionally, the root expression pointed to by the statement is interrogated to see if the ESUPPL_IS_LEFT_CHANGED or ESUPPL_IS_RIGHT_CHANGED bits are set. If one or both of the bits are found to be set, the root expression is placed into the expression simulation engine for further processing. When the statement's expression has completed its simulation, the value of the root expression is used to determine if the next_true or next_false path will be taken. If the value of the root expression is true, the next_true statement is loaded into the statement simulation engine. If the value of the root expression is false and the next_false pointer is NULL, this signifies that the current statement tree has completed for this timestep. At this point, the current statement will set the head bit in its root expression and is removed from the statement simulation engine. The next statement at the head of the pre-simulation statement queue is then loaded into the statement simulation engine. If next_false statement is not NULL, it is loaded into the statement simulation engine and work is done on that statement.
When a root expression is placed into the expression simulation engine, the tree is traversed, following the paths that have set ESUPPL_IS_LEFT_CHANGED or ESUPPL_IS_RIGHT_CHANGED bits set. Each expression tree is traversed depth first. When an expression is reached that does not have either of these bits set, we have reached the expression whose value has changed. When this expression is found, it is evaluated and the resulting value is stored into its value vector. Once this has occurred, the parent expression checks to see if the other child expression has changed value. If so, that child expression's tree is traversed. Once both child expressions contain the current value for the current timestep, the parent expression evaluates its expression with the values of its children and clears both the ESUPPL_IS_LEFT_CHANGED and ESUPPL_IS_RIGHT_CHANGED bits to indicate that both children were evaluated. The resulting value is stored into the current expression's value vector and the parent expression of the current expression is worked on. This evaluation process continues until the root expression of the tree has been evaluated. At this point the expression tree is removed from the expression simulation engine and the associated statement worked on by the statement simulation engine as specified above.

#include <stdio.h>
#include <assert.h>
#include <signal.h>
#include "defines.h"
#include "expr.h"
#include "func_unit.h"
#include "instance.h"
#include "iter.h"
#include "link.h"
#include "reentrant.h"
#include "sim.h"
#include "util.h"
#include "vector.h"
#include "vsignal.h"

Functions

void sim_display_thread (const thread *thr, bool show_queue, bool endl)
 Displays the given thread to standard output (for debug purposes only).

void sim_display_queue (thread *queue_head, thread *queue_tail)
void sim_display_active_queue ()
 Displays the current state of the active queue (for debug purposes only).

void sim_display_delay_queue ()
 Displays the current state of the delay queue (for debug purposes only).

void sim_display_all_list ()
 Displays the state of all threads.

threadsim_current_thread ()
 Returns a pointer to the current thread at the head of the active queue.

void sim_thread_pop_head ()
void sim_thread_insert_into_delay_queue (thread *thr, const sim_time *time)
 Inserts the given thread into the delay queue at the given time slot.

void sim_thread_push (thread *thr, const sim_time *time)
 Pushes given thread onto the active queue.

void sim_expr_changed (expression *expr, const sim_time *time)
 Adds specified expression's statement to pre-simulation statement queue.

threadsim_create_thread (thread *parent, statement *stmt, func_unit *funit)
threadsim_add_thread (thread *parent, statement *stmt, func_unit *funit, const sim_time *time)
 Creates a thread for the given statement and adds it to the thread simulation queue.

void sim_kill_thread (thread *thr)
void sim_kill_thread_with_funit (func_unit *funit)
 Deallocates thread and removes it from parent and thread queue lists for specified functional unit.

void sim_add_statics ()
bool sim_expression (expression *expr, thread *thr, const sim_time *time, bool lhs)
 Simulates a given expression tree, only performing needed operations as it traverses the tree.

void sim_thread (thread *thr, const sim_time *time)
 Simulates one thread until it has either completed or enters a context switch.

bool sim_simulate (const sim_time *time)
 Simulates current timestep.

void sim_initialize ()
 Initializes the simulator.

void sim_stop ()
 Causes the simulation to stop and enter into CLI mode.

void sim_finish ()
 Causes simulator to finish gracefully.

void sim_add_nonblock_assign (nonblock_assign *nba, int lhs_lsb, int lhs_msb, int rhs_lsb, int rhs_msb)
 Updates the given non-blocking assign structure and adds it to the non-blocking assignment queue.

void sim_perform_nba (const sim_time *time)
 Performs non-blocking assignment for currently queued assignment items for the current timestep.

void sim_dealloc ()
 Deallocates all memory for simulator.


Variables

char user_msg [USER_MSG_LENGTH]
bool debug_mode
exp_info exp_op_info [EXP_OP_NUM]
inst_linkinst_head
bool flag_use_command_line_debug
exp_linkstatic_expr_head = NULL
exp_linkstatic_expr_tail = NULL
threadall_head = NULL
threadall_tail = NULL
threadall_next = NULL
threadactive_head = NULL
threadactive_tail = NULL
threaddelayed_head = NULL
threaddelayed_tail = NULL
const char * thread_state_str [4] = {"NONE", "ACTIVE", "DELAYED", "WAITING"}
bool simulate = TRUE
bool force_stop = FALSE
nonblock_assign ** nba_queue = NULL
int nba_queue_size = 0
int nba_queue_curr_size = 0


Function Documentation

void sim_add_nonblock_assign nonblock_assign nba,
int  lhs_lsb,
int  lhs_msb,
int  rhs_lsb,
int  rhs_msb
 

Updates the given non-blocking assign structure and adds it to the non-blocking assignment queue.

Updates and adds the given non-blocking assignment structure to the simulation queue.

Parameters:
nba  Pointer to non-blocking assignment to updated and add
lhs_lsb  LSB of left-hand-side vector to assign
lhs_msb  MSB of left-hand-side vector to assign
rhs_lsb  LSB of right-hand-side vector to assign from
rhs_msb  MSB of right-hand-side vector to assign from

01227   { PROFILE(SIM_ADD_NONBLOCK_ASSIGN);
01228 
01229   /* Update the non-blocking assignment structure */
01230   nba->lhs_lsb = lhs_lsb;
01231   nba->lhs_msb = lhs_msb;
01232   nba->rhs_lsb = rhs_lsb;
01233   nba->rhs_msb = rhs_msb;
01234 
01235   /* Add it to the simulation queue (if it has not been already) */
01236   if( nba->suppl.added == 0 ) {
01237     nba_queue[nba_queue_curr_size++] = nba;
01238     nba->suppl.added = 1;
01239   }
01240 
01241   PROFILE_END;
01242 
01243 }

void sim_add_statics  )  [static]
 

Iterates through static expression list and causes the simulator to evaluate these expressions at simulation time.

00888                               { PROFILE(SIM_ADD_STATICS);
00889   
00890   exp_link* curr;   /* Pointer to current expression link */
00891   sim_time  time;   /* Current simulation time */
00892 
00893   /* Initialize the time to 0 */
00894   time.lo    = 0;
00895   time.hi    = 0;
00896   time.full  = 0;
00897   time.final = FALSE;
00898   
00899   curr = static_expr_head;
00900   while( curr != NULL ) {
00901     sim_expr_changed( curr->exp, &time );
00902     curr = curr->next;
00903   }
00904   
00905   exp_link_delete_list( static_expr_head, FALSE );
00906   static_expr_head = static_expr_tail = NULL;
00907 
00908   PROFILE_END;
00909   
00910 }

thread* sim_add_thread thread parent,
statement stmt,
func_unit funit,
const sim_time time
 

Creates a thread for the given statement and adds it to the thread simulation queue.

Returns:
Returns the pointer to the thread that was added to the active queue (if one was added).
Creates a new thread with the given information and adds the thread to the active queue to run. Returns a pointer to the newly created thread for joining/running purposes.
Parameters:
parent  Pointer to parent thread of the new thread to create (set to NULL if there is no parent thread)
stmt  Pointer to head statement to have new thread point to
funit  Pointer to functional unit that is creating this thread
time  Pointer to current simulation time

00662   { PROFILE(SIM_ADD_THREAD);
00663 
00664   thread* thr = NULL;  /* Pointer to added thread */
00665 
00666   /* Only add expression if it is the head statement of its statement block */
00667   if( stmt->suppl.part.head == 1 ) {
00668 
00669     /* Create thread, if needed */
00670     thr = sim_create_thread( parent, stmt, funit );
00671 
00672     /* Initialize thread runtime components */
00673     thr->suppl.all       = 0;
00674     thr->active_children = 0;
00675     thr->queue_prev      = NULL;
00676     thr->queue_next      = NULL;
00677 
00678     /*
00679      If the parent thread is specified, update our current time, increment the number of active children in the parent
00680      and add ourselves between the parent thread and its next pointer.
00681     */
00682     if( thr->parent != NULL ) {
00683 
00684       thr->curr_time = thr->parent->curr_time;
00685       thr->parent->active_children++;
00686 
00687       /* Place ourselves between the parent and its queue_next pointer */
00688       thr->queue_next = thr->parent->queue_next;
00689       thr->parent->queue_next = thr;
00690       if( thr->queue_next == NULL ) {
00691         active_tail = thr;
00692       } else {
00693         thr->queue_next->queue_prev = thr;
00694       }
00695       thr->queue_prev = thr->parent;
00696       thr->suppl.part.state = THR_ST_ACTIVE;    /* We will place the thread immediately into the active queue */
00697 
00698     } else {
00699 
00700       thr->curr_time = *time;
00701 
00702       /*
00703        If this statement is an always_comb or always_latch, add it to the delay list and change its right
00704        expression so that it will be executed at time 0 after all initial and always blocks have completed
00705       */
00706       if( (thr->curr->exp->op == EXP_OP_ALWAYS_COMB) || (thr->curr->exp->op == EXP_OP_ALWAYS_LATCH) ) {
00707 
00708         sim_time tmp_time;
00709 
00710         /* Add this thread into the delay queue at time 0 */
00711         tmp_time.lo    = 0;
00712         tmp_time.hi    = 0;
00713         tmp_time.full  = 0LL;
00714         tmp_time.final = FALSE;
00715         sim_thread_insert_into_delay_queue( thr, &tmp_time );
00716 
00717         /* Specify that this block should be evaluated */
00718         thr->curr->exp->right->suppl.part.eval_t = 1;
00719 
00720       } else {
00721 
00722         /* If the statement block is specified as a final block, add it to the end of the delay queue */
00723         if( thr->curr->suppl.part.final == 1 ) {
00724 
00725           sim_time tmp_time;
00726 
00727           tmp_time.lo    = 0xffffffff;
00728           tmp_time.hi    = 0xffffffff;
00729           tmp_time.full  = UINT64(0xffffffffffffffff);
00730           tmp_time.final = TRUE;
00731           sim_thread_insert_into_delay_queue( thr, &tmp_time );
00732 
00733         /* Otherwise, add it to the active thread list */
00734         } else {
00735 
00736           if( active_head == NULL ) {
00737             active_head = active_tail = thr;
00738           } else {
00739             thr->queue_prev         = active_tail;
00740             active_tail->queue_next = thr;
00741             active_tail             = thr;
00742           }
00743           thr->suppl.part.state = THR_ST_ACTIVE;
00744 
00745         }
00746 
00747       }
00748  
00749     }
00750 
00751 #ifdef DEBUG_MODE
00752     if( debug_mode && !flag_use_command_line_debug ) {
00753       printf( "Adding thread: " );
00754       sim_display_thread( thr, FALSE, TRUE );
00755       printf( "After thread is added to active queue...\n" );
00756       sim_display_active_queue();
00757       sim_display_all_list();
00758     }
00759 #endif
00760 
00761   }
00762 
00763   PROFILE_END;
00764 
00765   return( thr );
00766 
00767 }

thread* sim_create_thread thread parent,
statement stmt,
func_unit funit
[static]
 

Returns:
Returns a pointer to the newly allocated and initialized thread
Allocates a new thread for simulation purposes and initializes the thread structure with everything that can be done at time 0. This function does not place the thread into any queues (this is left to the sim_add_thread function).
Parameters:
parent  Pointer to parent thread (if one exists) of the newly created thread
stmt  Pointer to the statement that is the head statement of the thread's block
funit  Pointer to functional unit containing the new thread

00600   { PROFILE(SIM_CREATE_THREAD);
00601 
00602   thread* thr;  /* Pointer to newly allocated thread */
00603 
00604   /* If the next thread to use is empty, create a new one and add it to the end of the all pool */
00605   if( all_next == NULL ) {
00606 
00607     /* Allocate the new thread */
00608     thr           = (thread*)malloc_safe( sizeof( thread ) );
00609     thr->all_prev = NULL;
00610     thr->all_next = NULL;
00611 
00612     /* Place newly allocated thread in the all_threads pool */
00613     if( all_head == NULL ) {
00614       all_head = all_tail = thr;
00615     } else {
00616       thr->all_prev      = all_tail;
00617       all_tail->all_next = thr;
00618       all_tail           = thr;
00619     }
00620 
00621   /* Otherwise, select the next thread and advance the all_next pointer */
00622   } else {
00623 
00624     thr = all_next; 
00625     all_next = all_next->all_next;
00626 
00627   }
00628 
00629   /* Initialize the contents of the thread */
00630   thr->funit           = funit;
00631   thr->parent          = parent;
00632   thr->curr            = stmt;
00633   thr->ren             = NULL;
00634   thr->suppl.all       = 0;  /* Sets the current state of the thread to NONE */
00635   thr->curr_time.lo    = 0;
00636   thr->curr_time.hi    = 0;
00637   thr->curr_time.full  = 0LL;
00638   thr->curr_time.final = FALSE;
00639   thr->queue_prev      = NULL;
00640   thr->queue_next      = NULL;
00641 
00642   /* Add this thread to the given functional unit */
00643   funit_add_thread( funit, thr );
00644 
00645   PROFILE_END;
00646 
00647   return( thr );
00648 
00649 }

thread* sim_current_thread  ) 
 

Returns a pointer to the current thread at the head of the active queue.

Returns:
Returns a pointer to the current head of the active thread queue.

00304                              { PROFILE(SIM_CURRENT_THREAD);
00305 
00306   return( active_head );
00307 
00308 }

void sim_dealloc  ) 
 

Deallocates all memory for simulator.

Deallocates all allocated memory for simulation code.

01286                    { PROFILE(SIM_DEALLOC);
01287 
01288   thread* tmp;  /* Temporary thread pointer */
01289 
01290   /* Deallocate each thread in the all_threads array */
01291   while( all_head != NULL ) {
01292     tmp = all_head;
01293     all_head = all_head->all_next;
01294     free_safe( tmp, sizeof( thread ) );
01295   }
01296 
01297   all_head     = all_tail     = all_next = NULL;
01298   active_head  = active_tail  = NULL;
01299   delayed_head = delayed_tail = NULL;
01300 
01301   /* Deallocate all static expressions, if there are any */
01302   exp_link_delete_list( static_expr_head, FALSE );
01303 
01304   /* Deallocate the non-blocking assignment queue */
01305   free_safe( nba_queue, (sizeof( nonblock_assign ) * nba_queue_size) );
01306 
01307 #ifdef DEBUG_MODE
01308 #ifndef VPI_ONLY
01309   /* Clear CLI debug mode */
01310   cli_debug_mode = FALSE;
01311 #endif
01312 #endif
01313 
01314   PROFILE_END;
01315 
01316 }

void sim_display_active_queue  ) 
 

Displays the current state of the active queue (for debug purposes only).

Displays the current state of the active queue (for debug purposes only).

00259                                 {
00260 
00261   sim_display_queue( active_head, active_tail );
00262 
00263 }

void sim_display_all_list  ) 
 

Displays the state of all threads.

Displays the current state of the all_threads list (for debug purposes only).

00277                             {
00278 
00279   thread* thr;  /* Pointer to current thread */
00280 
00281   printf( "ALL THREADS:\n" );
00282 
00283   thr = all_head;
00284   while( thr != NULL ) {
00285     sim_display_thread( thr, FALSE, FALSE );
00286     if( thr == all_head ) {
00287       printf( "H" );
00288     }
00289     if( thr == all_tail ) {
00290       printf( "T" );
00291     }
00292     if( thr == all_next ) {
00293       printf( "N" );
00294     }
00295     printf( "\n" );
00296     thr = thr->all_next;
00297   }
00298 
00299 }

void sim_display_delay_queue  ) 
 

Displays the current state of the delay queue (for debug purposes only).

Displays the current state of the delay queue (for debug purposes only).

00268                                {
00269 
00270   sim_display_queue( delayed_head, delayed_tail );
00271 
00272 }

void sim_display_queue thread queue_head,
thread queue_tail
[static]
 

Displays the current state of the active queue (for debug purposes only).

Parameters:
queue_head  Pointer to head of queue to display
queue_tail  Pointer to tail of queue to display

00237   {
00238 
00239   thread* thr;  /* Pointer to current thread */
00240 
00241   thr = queue_head;
00242   while( thr != NULL ) {
00243     sim_display_thread( thr, TRUE, FALSE );
00244     if( thr == queue_head ) {
00245       printf( "H" );
00246     }
00247     if( thr == queue_tail ) {
00248       printf( "T" );
00249     }
00250     printf( "\n" );
00251     thr = thr->queue_next;
00252   }
00253 
00254 }

void sim_display_thread const thread thr,
bool  show_queue,
bool  endl
 

Displays the given thread to standard output (for debug purposes only).

Displays the contents of the given thread to standard output.

Parameters:
thr  Pointer to thread to display to standard output
show_queue  If set to TRUE, displays queue_prev/queue_next; otherwise, displays all_prev/all_next
endl  If set to TRUE, prints a newline character

00201   {
00202 
00203   if( !endl ) {
00204     printf( "    " );
00205   }
00206 
00207   /*@-duplicatequals -formattype@*/
00208   printf( "time %llu, ", thr->curr_time.full );
00209   /*@=duplicatequals =formattype@*/
00210 
00211   if( thr->curr == NULL ) {
00212     printf( "stmt NONE, " );
00213   } else {
00214     printf( "stmt %d, ", thr->curr->exp->id );
00215     printf( "%s, ", expression_string_op( thr->curr->exp->op ) );
00216     printf( "line %d, ", thr->curr->exp->line );
00217   }
00218 
00219   printf( "state %s ", thread_state_str[thr->suppl.part.state] );
00220   printf( "(%p, ", thr );
00221   printf( "parent=%p, ", thr->parent );
00222   printf( "prev=%p, ", (show_queue ? thr->queue_prev : thr->all_prev) );
00223   printf( "next=%p)  ", (show_queue ? thr->queue_next : thr->all_next) );
00224 
00225   if( endl ) {
00226     printf( "\n" );
00227   }
00228 
00229 }

void sim_expr_changed expression expr,
const sim_time time
 

Adds specified expression's statement to pre-simulation statement queue.

Traverses up expression tree pointed to by leaf node expr, setting the CHANGED bits as it reaches the root expression. When the root expression is found, the statement pointed to by the root's parent pointer is added to the pre-simulation statement queue for simulation at the end of the timestep. If, upon traversing the tree, an expression is found to already be have a CHANGED bit set, we know that the statement has already been added, so stop here and do not add the statement again.

Parameters:
expr  Pointer to expression that contains a changed signal value
time  Specifies current simulation time for the thread to push

00514   { PROFILE(SIM_EXPR_CHANGED);
00515 
00516   assert( expr != NULL );
00517 
00518   /* Set my left_changed bit to indicate to sim_expression that it should evaluate me */
00519   expr->suppl.part.left_changed = 1;
00520 
00521   while( ESUPPL_IS_ROOT( expr->suppl ) == 0 ) {
00522 
00523     expression* parent = expr->parent->expr;
00524 
00525 #ifdef DEBUG_MODE
00526     if( debug_mode ) {
00527       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In sim_expr_changed, expr %d, op %s, line %d, left_changed: %d, right_changed: %d, time: %llu",
00528                                   expr->id, expression_string_op( expr->op ), expr->line,
00529                                   ESUPPL_IS_LEFT_CHANGED( expr->suppl ),
00530                                   ESUPPL_IS_RIGHT_CHANGED( expr->suppl ),
00531                                   time->full );
00532       assert( rv < USER_MSG_LENGTH );
00533       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00534     }
00535 #endif
00536 
00537     /* If our expression is on the left of the parent, set the left_changed as needed */
00538     if( (parent->left != NULL) && (parent->left->id == expr->id) ) {
00539       
00540       /* If the bit we need to set is already set, stop iterating up tree */
00541       if( ESUPPL_IS_LEFT_CHANGED( parent->suppl ) == 1 ) {
00542         break;
00543       } else {
00544         parent->suppl.part.left_changed = 1;
00545         if( parent->op == EXP_OP_COND ) {
00546           parent->suppl.part.right_changed = 1;
00547         }
00548       }
00549 
00550     /* Otherwise, we assume that we match the right side */
00551     } else {
00552 
00553       /* If the bit we need to set is already set, stop iterating up tree */
00554       if( ESUPPL_IS_RIGHT_CHANGED( parent->suppl ) == 1 ) {
00555         break;
00556       } else {
00557         parent->suppl.part.right_changed = 1;
00558       }
00559 
00560     }
00561 
00562     expr = parent;
00563 
00564   }
00565 
00566   /* If we reached the root expression, push our thread onto the active queue */
00567   if( (ESUPPL_IS_ROOT( expr->suppl ) == 1) && (expr->parent->stmt != NULL) ) {
00568 
00569 #ifdef DEBUG_MODE
00570     if( debug_mode ) {
00571       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "In sim_expr_changed, expr %d, op %s, line %d, left_changed: %d, right_changed: %d, time: %llu",
00572                                   expr->id, expression_string_op( expr->op ), expr->line,
00573                                   ESUPPL_IS_LEFT_CHANGED( expr->suppl ),
00574                                   ESUPPL_IS_RIGHT_CHANGED( expr->suppl ),
00575                                   time->full );
00576       assert( rv < USER_MSG_LENGTH );
00577       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00578     }
00579 #endif
00580 
00581     funit_push_threads( expr->parent->stmt->funit, expr->parent->stmt, time );
00582 
00583   }
00584 
00585   PROFILE_END;
00586 
00587 }

bool sim_expression expression expr,
thread thr,
const sim_time time,
bool  lhs
 

Simulates a given expression tree, only performing needed operations as it traverses the tree.

Returns:
Returns TRUE if this expression has changed value from previous sim; otherwise, returns FALSE.
Recursively traverses specified expression tree, following the ESUPPL_IS_LEFT_CHANGED and ESUPPL_IS_RIGHT_CHANGED bits in the supplemental field. Once an expression is found that has neither bit set, perform the expression operation and move back up the tree. Once both left and right children have calculated values, perform the expression operation for the current expression, clear both changed bits and return.
Parameters:
expr  Pointer to expression to simulate
thr  Pointer to current thread that is being simulated
time  Pointer to current simulation time
lhs  Specifies if we should only traverse LHS expressions or RHS expressions

00928   { PROFILE(SIM_EXPRESSION);
00929 
00930   bool retval        = FALSE;  /* Return value for this function */
00931   bool left_changed  = FALSE;  /* Signifies if left expression tree has changed value */
00932   bool right_changed = FALSE;  /* Signifies if right expression tree has changed value */
00933 
00934   assert( expr != NULL );
00935 
00936   /* If our LHS mode matches the needed LHS mode, continue */
00937   if( ESUPPL_IS_LHS( expr->suppl ) == lhs ) {
00938 
00939 #ifdef DEBUG_MODE
00940     if( debug_mode ) {
00941       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "    In sim_expression %d, left_changed %d, right_changed %d, thread %p",
00942                                   expr->id, ESUPPL_IS_LEFT_CHANGED( expr->suppl ), ESUPPL_IS_RIGHT_CHANGED( expr->suppl ), thr );
00943       assert( rv < USER_MSG_LENGTH );
00944       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
00945     }
00946 #endif
00947 
00948     /* Traverse left child expression if it has changed */
00949     if( ((ESUPPL_IS_LEFT_CHANGED( expr->suppl ) == 1) ||
00950          (expr->op == EXP_OP_CASE)                    ||
00951          (expr->op == EXP_OP_CASEX)                   ||
00952          (expr->op == EXP_OP_CASEZ)) &&
00953         ((expr->op != EXP_OP_DLY_OP) || (expr->left == NULL) || (expr->left->op != EXP_OP_DELAY)) ) {
00954 
00955       /* Simulate the left expression if it has changed */
00956       if( expr->left != NULL ) {
00957         expr->suppl.part.left_changed = expr->suppl.part.clear_changed;
00958         left_changed = sim_expression( expr->left, thr, time, lhs );
00959       } else {
00960         expr->suppl.part.left_changed = 0;
00961         left_changed                  = TRUE;
00962       }
00963 
00964     }
00965 
00966     /* Traverse right child expression if it has changed */
00967     if( (ESUPPL_IS_RIGHT_CHANGED( expr->suppl ) == 1) &&
00968         ((expr->op != EXP_OP_DLY_OP) || !thr->suppl.part.exec_first) ) {
00969   
00970       /* Simulate the right expression if it has changed */
00971       if( expr->right != NULL ) {
00972         expr->suppl.part.right_changed = expr->suppl.part.clear_changed;
00973         right_changed = sim_expression( expr->right, thr, time, lhs );
00974       } else {
00975         expr->suppl.part.right_changed = 0;
00976         right_changed                  = TRUE;
00977       }
00978 
00979     }
00980 
00981     /*
00982      Now perform expression operation for this expression if left or right
00983      expressions trees have changed.
00984     */
00985     if( (ESUPPL_IS_ROOT( expr->suppl ) == 0) || (expr->parent->stmt == NULL) || (expr->parent->stmt->suppl.part.cont == 0) || left_changed || right_changed || (expr->table != NULL) ) {
00986       retval = expression_operate( expr, thr, time );
00987     }
00988 
00989   }
00990 
00991   PROFILE_END;
00992 
00993   return( retval );
00994 
00995 }

void sim_finish  ) 
 

Causes simulator to finish gracefully.

Causes the simulator to finish gracefully.

01209                   { PROFILE(SIM_FINISH);
01210 
01211   simulate = FALSE;
01212 
01213   PROFILE_END;
01214 
01215 }

void sim_initialize  ) 
 

Initializes the simulator.

Allocates thread arrays for simulation and initializes the contents of the active_threads array.

01160                       { PROFILE(SIM_INITIALIZE);
01161 
01162   /* Create non-blocking assignment queue */
01163   if( nba_queue_size > 0 ) {
01164     nba_queue           = (nonblock_assign**)malloc_safe( sizeof( nonblock_assign ) * nba_queue_size );
01165     nba_queue_curr_size = 0;
01166   }
01167 
01168   /* Add static values */
01169   sim_add_statics();
01170 
01171 #ifdef DEBUG_MODE
01172 #ifndef VPI_ONLY
01173   /* Set the CLI debug mode to the value of the general debug mode */
01174   cli_debug_mode = debug_mode;
01175 
01176   /* Add a signal handler for Ctrl-C if we are running in CLI mode */
01177   if( flag_use_command_line_debug ) {
01178     signal( SIGINT, cli_ctrl_c );
01179   }
01180 #endif
01181 #endif
01182 
01183   PROFILE_END;
01184 
01185 }

void sim_kill_thread thread thr  )  [static]
 

Removes the specified thread from its parent and the thread simulation queue and finally deallocates the specified thread.

Parameters:
thr  Thread to remove from simulation

00775   { PROFILE(SIM_KILL_THREAD);
00776 
00777   assert( thr != NULL );
00778 
00779 #ifdef DEBUG_MODE
00780   if( debug_mode && !flag_use_command_line_debug ) {
00781     printf( "Thread queue before thread is killed...\n" );
00782     sim_display_active_queue();
00783   }
00784 #endif
00785 
00786   if( thr->parent != NULL ) {
00787 
00788     /* Decrement the active children by one */
00789     thr->parent->active_children--;
00790 
00791     /* If we are the last child, re-insert the parent in our place (setting active_head to the parent) */
00792     if( thr->parent->active_children == 0 ) {
00793       thr->parent->queue_next = thr->queue_next;
00794       if( thr->queue_next == NULL ) {
00795         active_tail = thr->parent;
00796       } else {
00797         thr->queue_next->queue_prev = thr->parent;
00798       }
00799       active_head = thr->parent;
00800       thr->parent->curr_time = thr->curr_time;
00801       thr->parent->suppl.part.state = THR_ST_ACTIVE;  /* Specify that the parent thread is now back in the active queue */
00802     } else {
00803       active_head = active_head->queue_next;
00804       if( active_head == NULL ) {
00805         active_tail = NULL;
00806       }
00807     }
00808 
00809   } else {
00810 
00811     active_head = active_head->queue_next;
00812     if( active_head == NULL ) {
00813       active_tail = NULL;
00814     } else {
00815       active_head->queue_prev = NULL;  /* Here for debug purposes - TBD */
00816     }
00817 
00818   }
00819 
00820   /* Check to make sure that the thread is not in the waiting state */
00821   assert( thr->suppl.part.state != THR_ST_WAITING );
00822 
00823   /* Remove this thread from its functional unit */
00824   funit_delete_thread( thr->funit, thr );
00825 
00826   /* Finally, park this thread at the end of the all_queue (if its not already there) */
00827   if( thr != all_tail ) {
00828     if( thr == all_head ) {
00829       all_head           = thr->all_next;
00830       all_head->all_prev = NULL;
00831     } else {
00832       thr->all_prev->all_next = thr->all_next;
00833       thr->all_next->all_prev = thr->all_prev;
00834     }
00835     thr->all_prev      = all_tail;
00836     thr->all_next      = NULL;
00837     all_tail->all_next = thr;
00838     all_tail           = thr;
00839   }
00840 
00841   /* If the all_next pointer is NULL, point it to the moved thread */
00842   if( all_next == NULL ) {
00843     all_next = all_tail;
00844   }
00845 
00846 #ifdef DEBUG_MODE
00847   if( debug_mode && !flag_use_command_line_debug ) {
00848     printf( "Thread queue after thread is killed...\n" );
00849     sim_display_active_queue();
00850     sim_display_all_list();
00851   }
00852 #endif
00853 
00854   PROFILE_END;
00855 
00856 }

void sim_kill_thread_with_funit func_unit funit  ) 
 

Deallocates thread and removes it from parent and thread queue lists for specified functional unit.

Searches the current state of the active queue for the thread containing the specified head statement. If a thread was found to match, kill it. This function is called whenever the DISABLE statement is run.

Parameters:
funit  Pointer to functional unit of thread to kill

00865   { PROFILE(SIM_KILL_THREAD_WITH_FUNIT);
00866 
00867   thread* thr;  /* Pointer to current thread */
00868 
00869   assert( funit != NULL );
00870 
00871   /* Kill any threads that match the given functional unit or are children of it */
00872   thr = all_head;
00873   while( thr != NULL ) {
00874     if( (thr->funit == funit) || (funit_is_child_of( funit, thr->funit )) ) {
00875       thr->suppl.part.kill = 1;
00876     }
00877     thr = thr->all_next;
00878   }
00879 
00880   PROFILE_END;
00881 
00882 }

void sim_perform_nba const sim_time time  ) 
 

Performs non-blocking assignment for currently queued assignment items for the current timestep.

Performs non-blocking assignment for the nba elements in the current nba simulation queue.

Parameters:
time  Current simulation time

01250   { PROFILE(SIM_PERFORM_NBA);
01251 
01252   int              i;
01253   bool             changed;
01254   nonblock_assign* nba;
01255 
01256   for( i=0; i<nba_queue_curr_size; i++ ) {
01257     nba     = nba_queue[i];
01258     changed = vector_part_select_push( nba->lhs_sig->value, nba->lhs_lsb, nba->lhs_msb, nba->rhs_vec, nba->rhs_lsb, nba->rhs_msb, nba->suppl.is_signed );
01259     nba->lhs_sig->value->suppl.part.set = 1;
01260 #ifdef DEBUG_MODE
01261 #ifndef VPI_ONLY
01262     if( debug_mode && (!flag_use_command_line_debug || cli_debug_mode) ) {
01263       if( i == 0 ) {
01264         printf( "Non-blocking assignments:\n" );
01265       }
01266       printf( "    " );  vsignal_display( nba->lhs_sig );
01267     }
01268 #endif
01269 #endif
01270     if( changed ) { 
01271       vsignal_propagate( nba->lhs_sig, time );
01272     }
01273     nba->suppl.added = 0;
01274   }
01275 
01276   /* Clear the nba queue */
01277   nba_queue_curr_size = 0;
01278 
01279   PROFILE_END;
01280 
01281 }

bool sim_simulate const sim_time time  ) 
 

Simulates current timestep.

Returns:
Returns TRUE if simulation should continue; otherwise, returns FALSE to indicate that simulation should no longer continue.
This function is the heart of the simulation engine. It is called by the db_do_timestep() function in db.c and moves the statements and expressions into the appropriate simulation functions. See above explanation on this procedure.
Parameters:
time  Current simulation time from dumpfile or simulator

01119   { PROFILE(SIM_SIMULATE);
01120 
01121   /* Simulate all threads in the active queue */
01122   while( active_head != NULL ) {
01123     sim_thread( active_head, time );
01124   }
01125 
01126   while( (delayed_head != NULL) && TIME_CMP_LE(delayed_head->curr_time, *time) ) {
01127 
01128     active_head  = active_tail = delayed_head;
01129     delayed_head = delayed_head->queue_next;
01130     active_head->queue_prev = active_head->queue_next = NULL;
01131     if( delayed_head != NULL ) {
01132       delayed_head->queue_prev = NULL;
01133     } else {
01134       delayed_tail = NULL;
01135     }
01136     active_head->suppl.part.state = THR_ST_ACTIVE;
01137 
01138     while( active_head != NULL ) {
01139       sim_thread( active_head, time );
01140     }
01141 
01142   }
01143 
01144 #ifdef DEBUG_MODE
01145   if( debug_mode && !flag_use_command_line_debug ) {
01146     printf( "After delay simulation...\n" );
01147     sim_display_delay_queue();
01148   }
01149 #endif
01150 
01151   PROFILE_END;
01152 
01153   return( simulate );
01154 
01155 }

void sim_stop  ) 
 

Causes the simulation to stop and enter into CLI mode.

Stops the simulation and gets the user to a CLI prompt, if possible.

01190                 { PROFILE(SIM_STOP);
01191 
01192 #ifdef DEBUG_MODE
01193 #ifndef VPI_ONLY
01194   force_stop = TRUE;
01195 #else
01196   simulate = FALSE;
01197 #endif
01198 #else
01199   simulate = FALSE;
01200 #endif
01201 
01202   PROFILE_END;
01203 
01204 }

void sim_thread thread thr,
const sim_time time
 

Simulates one thread until it has either completed or enters a context switch.

Performs statement simulation as described above. Calls expression simulator if the associated root expression is specified that signals have changed value within it. Continues to run for current statement tree until statement tree hits a wait-for-event condition (or we reach the end of a simulation tree).

Parameters:
thr  Pointer to current thread to simulate
time  Current simulation time to simulate

01006   { PROFILE(SIM_THREAD);
01007 
01008   statement* stmt;                  /* Pointer to current statement to evaluate */
01009   bool       expr_changed = FALSE;  /* Specifies if expression tree was modified in any way */
01010 
01011   /* If the thread has a reentrant structure assigned to it, pop it */
01012   if( thr->ren != NULL ) {
01013     reentrant_dealloc( thr->ren, thr->funit, FALSE );
01014     thr->ren = NULL;
01015   }
01016 
01017   /* Set the value of stmt with the head_stmt */
01018   stmt = thr->curr;
01019 
01020 
01021   while( (stmt != NULL) && !thr->suppl.part.kill && simulate ) {
01022 
01023 #ifdef DEBUG_MODE
01024 #ifndef VPI_ONLY
01025     cli_execute( time, force_stop, stmt );
01026     force_stop = FALSE;
01027 #endif
01028 #endif
01029 
01030     /* Place expression in expression simulator and run */
01031     expr_changed = sim_expression( stmt->exp, thr, time, FALSE );
01032 
01033 #ifdef DEBUG_MODE
01034     if( debug_mode ) {
01035       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "  Executed statement %d, expr changed %d, thread %p", stmt->exp->id, expr_changed, thr );
01036       assert( rv < USER_MSG_LENGTH );
01037       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01038     }
01039 #endif
01040       
01041     thr->curr = stmt;
01042 
01043     /* Set exec_first to FALSE */
01044     thr->suppl.part.exec_first = 0;
01045 
01046     if( stmt->suppl.part.cont == 1 ) {
01047        /* If this is a continuous assignment, don't traverse next pointers. */
01048        stmt = NULL;
01049     } else {
01050       if( ESUPPL_IS_TRUE( stmt->exp->suppl ) == 1 ) {
01051         stmt = stmt->next_true;
01052       } else {
01053         stmt = stmt->next_false;
01054       }
01055     }
01056 
01057   }
01058 
01059   /* If this is the last statement in the tree with no loopback, kill the current thread */
01060   if( (expr_changed && 
01061       (((thr->curr->next_true == NULL) && (thr->curr->next_false == NULL)) ||
01062        (!EXPR_IS_CONTEXT_SWITCH( thr->curr->exp ) && !thr->curr->suppl.part.cont))) ||
01063       (thr->curr == NULL) ||
01064       (!expr_changed && (stmt == NULL) &&
01065        ((thr->curr->exp->op == EXP_OP_CASE)  ||
01066         (thr->curr->exp->op == EXP_OP_CASEX) ||
01067         (thr->curr->exp->op == EXP_OP_CASEZ) ||
01068         (thr->curr->exp->op == EXP_OP_DEFAULT))) ||
01069       thr->suppl.part.kill ||
01070       !simulate ) {
01071 
01072 #ifdef DEBUG_MODE
01073     if( debug_mode ) {
01074       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Completed thread %p, killing...\n", thr );
01075       assert( rv < USER_MSG_LENGTH );
01076       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01077     }
01078 #endif
01079  
01080     /* Destroy the thread */
01081     sim_kill_thread( thr );
01082 
01083   /* Otherwise, we are switching contexts */
01084   } else {
01085 
01086 #ifdef DEBUG_MODE
01087     if( debug_mode ) {
01088       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Switching context of thread %p...\n", thr );
01089       assert( rv < USER_MSG_LENGTH );
01090       print_output( user_msg, DEBUG, __FILE__, __LINE__ );
01091     }
01092 #endif
01093 
01094     /* Pop this packet out of the active queue */
01095     if( ((thr->curr->exp->op != EXP_OP_DELAY) && 
01096          ((thr->curr->exp->op != EXP_OP_DLY_ASSIGN) || (thr->curr->exp->right->left->op != EXP_OP_DELAY))) ||
01097         time->final ) {
01098       sim_thread_pop_head();
01099     } else {
01100       thr->suppl.part.exec_first = 1;
01101     }
01102 
01103   }
01104 
01105   PROFILE_END;
01106 
01107 }

void sim_thread_insert_into_delay_queue thread thr,
const sim_time time
 

Inserts the given thread into the delay queue at the given time slot.

This function is called by the expression_op_func__delay() function.

Parameters:
thr  Pointer to the thread to add to the delay queue
time  Pointer to time to insert the given thread

00362   { PROFILE(SIM_THREAD_INSERT_INTO_DELAY_QUEUE);
00363 
00364   thread* curr;  /* Pointer to current thread in delayed queue to compare against */
00365 
00366 #ifdef DEBUG_MODE
00367   if( debug_mode && !flag_use_command_line_debug ) {
00368     printf( "Before delay thread is inserted for time %llu...\n", time->full );
00369   }
00370 #endif
00371 
00372   if( thr != NULL ) {
00373 
00374     assert( thr->suppl.part.state != THR_ST_DELAYED );
00375 
00376 #ifdef DEBUG_MODE
00377     if( debug_mode && !flag_use_command_line_debug ) {
00378       sim_display_delay_queue();
00379     }
00380 #endif
00381 
00382     /* If the thread is currently in the active state, remove it from the active queue now */
00383     if( thr->suppl.part.state == THR_ST_ACTIVE ) {
00384  
00385       /* Move the head pointer */
00386       active_head = active_head->queue_next;
00387       if( active_head == NULL ) {
00388         active_tail = NULL;
00389       } else {
00390         active_head->queue_prev = NULL;   /* TBD - Placed here for help in debug */
00391       }
00392 
00393     }
00394 
00395     /* Specify that the thread is queued and delayed */
00396     thr->suppl.part.state = THR_ST_DELAYED;
00397 
00398     /* Set the thread simulation time to the given time */
00399     thr->curr_time = *time;
00400 
00401     /* Add the given thread to the delayed queue in simulation time order */
00402     if( delayed_head == NULL ) {
00403       delayed_head = delayed_tail = thr;
00404       thr->queue_prev = NULL;
00405       thr->queue_next = NULL;
00406     } else {
00407       curr = delayed_tail;
00408       while( (curr != NULL) && TIME_CMP_GT(curr->curr_time, *time) ) {
00409         curr = curr->queue_prev;
00410       }
00411       if( curr == NULL ) {
00412         thr->queue_prev          = NULL;
00413         thr->queue_next          = delayed_head;
00414         delayed_head->queue_prev = thr;
00415         delayed_head             = thr;
00416       } else if( curr == delayed_tail ) {
00417         thr->queue_prev          = delayed_tail;
00418         thr->queue_next          = NULL;
00419         delayed_tail->queue_next = thr;
00420         delayed_tail             = thr;
00421       } else {
00422         thr->queue_prev             = curr;
00423         thr->queue_next             = curr->queue_next;
00424         thr->queue_next->queue_prev = thr;
00425         curr->queue_next            = thr;
00426       }
00427     }
00428     
00429 #ifdef DEBUG_MODE
00430     if( debug_mode && !flag_use_command_line_debug ) {
00431       printf( "After delay thread is inserted...\n" );
00432       sim_display_delay_queue();
00433       sim_display_all_list();
00434     }
00435 #endif
00436 
00437   }
00438 
00439   PROFILE_END;
00440 
00441 }

void sim_thread_pop_head  )  [static]
 

Pops the head thread from the active queue without deallocating the thread.

00313                                   { PROFILE(SIM_THREAD_POP_HEAD);
00314 
00315   thread* thr = active_head;  /* Pointer to head of active queue */
00316 
00317 #ifdef DEBUG_MODE
00318   if( debug_mode && !flag_use_command_line_debug ) {
00319     printf( "Before thread is popped from active queue...\n" );
00320     sim_display_active_queue();
00321   }
00322 #endif
00323 
00324   /* Move the head pointer */
00325   active_head = active_head->queue_next;
00326   if( active_head == NULL ) {
00327     active_tail = NULL;
00328   } else {
00329     active_head->queue_prev = NULL;   /* TBD - Placed here for help in debug */
00330   }
00331 
00332   /* Advance the curr pointer if we call sim_add_thread */
00333   if( (thr->curr->exp->op == EXP_OP_FORK)      ||
00334       (thr->curr->exp->op == EXP_OP_JOIN)      ||  /* TBD */
00335       (thr->curr->exp->op == EXP_OP_FUNC_CALL) ||
00336       (thr->curr->exp->op == EXP_OP_TASK_CALL) ||
00337       (thr->curr->exp->op == EXP_OP_NB_CALL) ) {
00338     thr->curr = thr->curr->next_true;
00339     thr->suppl.part.state = THR_ST_NONE;
00340   } else {
00341     thr->suppl.part.state      = THR_ST_WAITING;
00342     thr->suppl.part.exec_first = 1; 
00343   }
00344 
00345 #ifdef DEBUG_MODE
00346   if( debug_mode && !flag_use_command_line_debug ) {
00347     printf( "After thread is popped from active queue...\n" );
00348     sim_display_active_queue();
00349   }
00350 #endif
00351 
00352   PROFILE_END;
00353 
00354 }

void sim_thread_push thread thr,
const sim_time time
 

Pushes given thread onto the active queue.

Adds the specified thread to the end of the current simulation queue. This function gets called whenever a head statement has a signal change or the head statement is a delay operation and

Parameters:
thr  Pointer to thread to add to the tail of the simulation queue
time  Current simulation time of thread to push

00451   { PROFILE(SIM_THREAD_PUSH);
00452 
00453   exp_op_type op;  /* Operation type of current expression in given thread */
00454 
00455 #ifdef DEBUG_MODE
00456   if( debug_mode && !flag_use_command_line_debug ) {
00457     printf( "Before thread is pushed...\n" );
00458     sim_display_active_queue();
00459   }
00460 #endif
00461 
00462   /* Set the state to ACTIVE */
00463   thr->suppl.part.state = THR_ST_ACTIVE;
00464 
00465   /* Set the current time of the thread to the given value */
00466   op = thr->curr->exp->op;
00467   if( (op == EXP_OP_PEDGE)       ||
00468       (op == EXP_OP_NEDGE)       ||
00469       (op == EXP_OP_AEDGE)       ||
00470       (op == EXP_OP_EOR)         ||
00471       (op == EXP_OP_WAIT)        ||
00472       (op == EXP_OP_SLIST)       ||
00473       (op == EXP_OP_ALWAYS_COMB) ||
00474       (op == EXP_OP_ALWAYS_LATCH) ) {
00475     thr->curr_time = *time;
00476   }
00477 
00478   /* Set the active next and prev pointers to NULL */
00479   thr->queue_prev = thr->queue_next = NULL;
00480 
00481   /* Add the given thread to the end of the active_threads queue */
00482   if( active_head == NULL ) {
00483     active_head = active_tail = thr;
00484   } else {
00485     thr->queue_prev         = active_tail;
00486     active_tail->queue_next = thr;
00487     active_tail             = thr;
00488   }
00489 
00490 #ifdef DEBUG_MODE
00491   if( debug_mode && !flag_use_command_line_debug ) {
00492     printf( "After thread is pushed...\n" );
00493     sim_display_active_queue();
00494     sim_display_all_list();
00495   }
00496 #endif
00497 
00498   PROFILE_END;
00499 
00500 }


Variable Documentation

thread* active_head = NULL [static]
 

Pointer to head of active thread list.

thread* active_tail = NULL [static]
 

Pointer to tail of active thread list.

thread* all_head = NULL [static]
 

Head of list of all allocated threads.

thread* all_next = NULL [static]
 

Pointer to next thread to allocate.

thread* all_tail = NULL [static]
 

Tail of list of all allocated threads.

bool debug_mode
 

If set to TRUE, causes debug information to be spewed to screen.

thread* delayed_head = NULL [static]
 

Pointer to head of delayed thread list.

thread* delayed_tail = NULL [static]
 

Pointer to tail of delayed thread list.

exp_info exp_op_info[EXP_OP_NUM]
 

Array containing static information about expression operation types. NOTE: This structure MUST be updated if a new expression is added! The third argument is an initialization to the exp_info_s structure.

bool flag_use_command_line_debug
 

Specifies whether the command-line debugger should be enabled

bool force_stop = FALSE [static]
 

Causes simulation to stop and invoke the CLI prompt, if possible.

inst_link* inst_head
 

nonblock_assign** nba_queue = NULL [static]
 

Non-blocking assignment queue.

int nba_queue_curr_size = 0 [static]
 

The current number of nba structures in the nba_queue.

int nba_queue_size = 0
 

The allocated size of the non-blocking assignment queue.

bool simulate = TRUE [static]
 

Global variable used to cause simulator to stop simulation. Do not directly modify this variable!

exp_link* static_expr_head = NULL
 

Pointer to head of expression list that contains all expressions that contain static (non-changing) values. These expressions will be forced to be simulated, making sure that correct coverage numbers for expressions containing static values is maintained.

exp_link* static_expr_tail = NULL
 

Pointer to tail of expression list that contains all expressions that contain static (non-changing) values. These expressions will be forced to be simulated, making sure that correct coverage numbers for expressions containing static values is maintained.

const char* thread_state_str[4] = {"NONE", "ACTIVE", "DELAYED", "WAITING"} [static]
 

List of thread state string names.

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:24 2009 for Covered by doxygen 1.3.4