sim.h File Reference

Contains functions for simulation engine. More...

#include "defines.h"

Go to the source code of this file.

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_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_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_expr_changed (expression *expr, const sim_time *time)
 Adds specified expression's statement to pre-simulation statement queue.
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_with_funit (func_unit *funit)
 Deallocates thread and removes it from parent and thread queue lists for specified functional unit.
void sim_thread_push (thread *thr, const sim_time *time)
 Pushes given thread onto the active queue.
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.

Detailed Description

Contains functions for simulation engine.

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
6/20/2002

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

References nonblock_assign_s::added, nonblock_assign_s::lhs_lsb, nonblock_assign_s::lhs_msb, nba_queue_curr_size, PROFILE, PROFILE_END, nonblock_assign_s::rhs_lsb, nonblock_assign_s::rhs_msb, and nonblock_assign_s::suppl.

Referenced by expression_assign().

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

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

References thread_s::active_children, thread_s::all, thread_s::curr, thread_s::curr_time, debug_mode, esuppl_u::eval_t, statement_s::exp, EXP_OP_ALWAYS_COMB, EXP_OP_ALWAYS_LATCH, FALSE, sim_time_s::final, flag_use_command_line_debug, sim_time_s::full, sim_time_s::hi, sim_time_s::lo, expression_s::op, thread_s::parent, esuppl_u::part, thread_s::part, statement_s::part, PROFILE, PROFILE_END, thread_s::queue_next, thread_s::queue_prev, expression_s::right, sim_create_thread(), sim_display_active_queue(), sim_display_all_list(), sim_display_thread(), sim_thread_insert_into_delay_queue(), expression_s::suppl, thread_s::suppl, statement_s::suppl, THR_ST_ACTIVE, and TRUE.

Referenced by expression_op_func__fork(), expression_op_func__func_call(), expression_op_func__nb_call(), expression_op_func__task_call(), and statement_db_read().

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

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.

References PROFILE.

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

void sim_dealloc (  ) 

Deallocates all memory for simulator.

Deallocates all allocated memory for simulation code.

References thread_s::all_next, cli_debug_mode, exp_link_delete_list(), FALSE, free_safe, nba_queue_size, PROFILE, and PROFILE_END.

Referenced by covered_end_of_sim(), parse_and_score_dumpfile(), and parse_design().

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

void sim_display_active_queue (  ) 

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

References sim_display_queue().

Referenced by sim_add_thread(), sim_kill_thread(), sim_thread_pop_head(), and sim_thread_push().

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

void sim_display_all_list (  ) 

Displays the state of all threads.

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

References thread_s::all_next, FALSE, and sim_display_thread().

Referenced by sim_add_thread(), sim_kill_thread(), sim_thread_insert_into_delay_queue(), and sim_thread_push().

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

void sim_display_delay_queue (  ) 

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

References sim_display_queue().

Referenced by sim_simulate(), and sim_thread_insert_into_delay_queue().

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

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

References thread_s::all_next, thread_s::all_prev, thread_s::curr, thread_s::curr_time, statement_s::exp, expression_string_op(), sim_time_s::full, expression_s::id, expression_s::line, expression_s::op, thread_s::parent, thread_s::part, thread_s::queue_next, thread_s::queue_prev, thread_s::suppl, and thread_state_str.

Referenced by sim_add_thread(), sim_display_all_list(), and sim_display_queue().

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

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

References DEBUG, debug_mode, ESUPPL_IS_LEFT_CHANGED, ESUPPL_IS_RIGHT_CHANGED, ESUPPL_IS_ROOT, EXP_OP_COND, expr_stmt_u::expr, expression_string_op(), sim_time_s::full, statement_s::funit, funit_push_threads(), expression_s::id, expression_s::left, esuppl_u::left_changed, expression_s::line, expression_s::op, expression_s::parent, esuppl_u::part, print_output(), PROFILE, PROFILE_END, esuppl_u::right_changed, expr_stmt_u::stmt, expression_s::suppl, user_msg, and USER_MSG_LENGTH.

Referenced by fsm_table_set(), sim_add_statics(), and vsignal_propagate().

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

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

References esuppl_u::clear_changed, DEBUG, debug_mode, ESUPPL_IS_LEFT_CHANGED, ESUPPL_IS_LHS, ESUPPL_IS_RIGHT_CHANGED, ESUPPL_IS_ROOT, EXP_OP_CASE, EXP_OP_CASEX, EXP_OP_CASEZ, EXP_OP_DELAY, EXP_OP_DLY_OP, expression_operate(), FALSE, expression_s::id, expression_s::left, esuppl_u::left_changed, expression_s::op, expression_s::parent, statement_s::part, thread_s::part, esuppl_u::part, print_output(), PROFILE, PROFILE_END, expression_s::right, esuppl_u::right_changed, sim_expression(), expr_stmt_u::stmt, statement_s::suppl, thread_s::suppl, expression_s::suppl, expression_s::table, TRUE, user_msg, and USER_MSG_LENGTH.

Referenced by expression_assign(), expression_op_func__add_a(), expression_op_func__and_a(), expression_op_func__arshift_a(), expression_op_func__divide_a(), expression_op_func__lshift_a(), expression_op_func__mod_a(), expression_op_func__multiply_a(), expression_op_func__or_a(), expression_op_func__rshift_a(), expression_op_func__sub_a(), expression_op_func__xor_a(), sim_expression(), and sim_thread().

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

void sim_finish (  ) 

Causes simulator to finish gracefully.

Causes the simulator to finish gracefully.

References FALSE, PROFILE, PROFILE_END, and simulate.

Referenced by expression_op_func__finish().

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

void sim_initialize (  ) 

Initializes the simulator.

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

References cli_ctrl_c(), cli_debug_mode, debug_mode, flag_use_command_line_debug, malloc_safe, nba_queue_curr_size, nba_queue_size, PROFILE, PROFILE_END, and sim_add_statics().

Referenced by covered_sim_calltf(), and parse_and_score_dumpfile().

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

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

References thread_s::all_next, thread_s::funit, funit_is_child_of(), thread_s::part, PROFILE, PROFILE_END, and thread_s::suppl.

Referenced by expression_op_func__disable().

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

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

References nonblock_assign_s::added, cli_debug_mode, debug_mode, flag_use_command_line_debug, nonblock_assign_s::is_signed, nonblock_assign_s::lhs_lsb, nonblock_assign_s::lhs_msb, nonblock_assign_s::lhs_sig, nba_queue_curr_size, vsuppl_u::part, PROFILE, PROFILE_END, nonblock_assign_s::rhs_lsb, nonblock_assign_s::rhs_msb, nonblock_assign_s::rhs_vec, vsuppl_u::set, vector_s::suppl, nonblock_assign_s::suppl, vsignal_s::value, vector_part_select_push(), vsignal_display(), and vsignal_propagate().

Referenced by db_do_timestep().

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

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

References thread_s::curr_time, debug_mode, flag_use_command_line_debug, thread_s::part, PROFILE, PROFILE_END, thread_s::queue_next, thread_s::queue_prev, sim_display_delay_queue(), sim_thread(), simulate, thread_s::suppl, THR_ST_ACTIVE, and TIME_CMP_LE.

Referenced by db_do_timestep().

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

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.

References FALSE, force_stop, PROFILE, PROFILE_END, simulate, and TRUE.

Referenced by expression_op_func__stop().

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

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

References cli_execute(), thread_s::curr, DEBUG, debug_mode, ESUPPL_IS_TRUE, statement_s::exp, EXP_OP_CASE, EXP_OP_CASEX, EXP_OP_CASEZ, EXP_OP_DEFAULT, EXP_OP_DELAY, EXP_OP_DLY_ASSIGN, EXPR_IS_CONTEXT_SWITCH, FALSE, sim_time_s::final, force_stop, thread_s::funit, expression_s::id, expression_s::left, statement_s::next_false, statement_s::next_true, expression_s::op, statement_s::part, thread_s::part, print_output(), PROFILE, PROFILE_END, reentrant_dealloc(), thread_s::ren, expression_s::right, sim_expression(), sim_kill_thread(), sim_thread_pop_head(), simulate, expression_s::suppl, statement_s::suppl, thread_s::suppl, user_msg, and USER_MSG_LENGTH.

Referenced by expression_op_func__func_call(), expression_op_func__nb_call(), and sim_simulate().

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

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

References thread_s::curr_time, debug_mode, flag_use_command_line_debug, sim_time_s::full, thread_s::part, PROFILE, PROFILE_END, thread_s::queue_next, thread_s::queue_prev, sim_display_all_list(), sim_display_delay_queue(), thread_s::suppl, THR_ST_ACTIVE, THR_ST_DELAYED, and TIME_CMP_GT.

Referenced by expression_op_func__delay(), and sim_add_thread().

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

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

References thread_s::curr, thread_s::curr_time, debug_mode, statement_s::exp, EXP_OP_AEDGE, EXP_OP_ALWAYS_COMB, EXP_OP_ALWAYS_LATCH, EXP_OP_EOR, EXP_OP_NEDGE, EXP_OP_PEDGE, EXP_OP_SLIST, EXP_OP_WAIT, flag_use_command_line_debug, expression_s::op, thread_s::part, PROFILE, PROFILE_END, thread_s::queue_next, thread_s::queue_prev, sim_display_active_queue(), sim_display_all_list(), thread_s::suppl, and THR_ST_ACTIVE.

Referenced by funit_push_threads().

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

Generated on Sun Nov 21 00:55:41 2010 for Covered by  doxygen 1.6.3