vcd.c File Reference

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "defines.h"
#include "vcd.h"
#include "db.h"
#include "util.h"
#include "symtable.h"

Functions

static void vcd_parse_def_ignore (FILE *vcd)
static void vcd_parse_def_var (FILE *vcd)
static void vcd_parse_def_scope (FILE *vcd)
static void vcd_parse_def (FILE *vcd)
static void vcd_parse_sim_vector (FILE *vcd, char *value)
static void vcd_parse_sim_real (FILE *vcd, char *value)
static void vcd_parse_sim_ignore (FILE *vcd)
static void vcd_parse_sim (FILE *vcd)
void vcd_parse (const char *vcd_file)
 Parses specified VCD file, storing information into database.

Variables

char user_msg [USER_MSG_LENGTH]
symtablevcd_symtab
int vcd_symtab_size
symtable ** timestep_tab

Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
7/21/2002

Function Documentation

void vcd_parse ( const char *  vcd_file  ) 

Parses specified VCD file, storing information into database.

Exceptions:
anonymous Throw Throw vcd_parse_def vcd_parse_sim

Reads specified VCD file for relevant information and calls the database functions when appropriate to store this information. This replaces the need for a lexer and parser which should increase performance.

Parameters:
vcd_file Name of VCD file to parse

References Catch_anonymous, FATAL, free_safe, malloc_safe_nolimit, print_output(), PROFILE, PROFILE_END, symtable_create(), symtable_dealloc(), Throw, Try, vcd_parse_def(), vcd_parse_sim(), and vcd_symtab_size.

Referenced by parse_and_score_dumpfile().

00428   { PROFILE(VCD_PARSE);
00429 
00430   FILE* vcd_handle;        /* Pointer to opened VCD file */
00431 
00432   if( (vcd_handle = fopen( vcd_file, "r" )) != NULL ) {
00433 
00434     unsigned int rv;
00435 
00436     /* Create initial symbol table */
00437     vcd_symtab = symtable_create();
00438 
00439     Try {
00440 
00441       vcd_parse_def( vcd_handle );
00442 
00443       /* Create timestep symbol table array */
00444       if( vcd_symtab_size > 0 ) {
00445         timestep_tab = malloc_safe_nolimit( sizeof( symtable*) * vcd_symtab_size );
00446       }
00447     
00448       vcd_parse_sim( vcd_handle );
00449 
00450     } Catch_anonymous {
00451       symtable_dealloc( vcd_symtab );
00452       free_safe( timestep_tab, (sizeof( symtable*) * vcd_symtab_size) );
00453       rv = fclose( vcd_handle );
00454       assert( rv == 0 );
00455       Throw 0;
00456     }
00457 
00458     /* Deallocate memory */
00459     symtable_dealloc( vcd_symtab );
00460     free_safe( timestep_tab, (sizeof( symtable*) * vcd_symtab_size) );
00461 
00462     /* Close VCD file */
00463     rv = fclose( vcd_handle );
00464     assert( rv == 0 );
00465 
00466   } else {
00467 
00468     print_output( "Unable to open specified VCD file", FATAL, __FILE__, __LINE__ );
00469     Throw 0;
00470 
00471   }
00472 
00473   PROFILE_END;
00474 
00475 }

static void vcd_parse_def ( FILE *  vcd  )  [static]
Exceptions:
anonymous Throw Throw Throw vcd_parse_def_scope vcd_parse_def_var

Parses all definition information from specified file.

Parameters:
vcd File handle pointer to opened VCD file

References db_check_dumpfile_scopes(), db_vcd_upscope(), FALSE, FATAL, print_output(), PROFILE, PROFILE_END, Throw, TRUE, user_msg, USER_MSG_LENGTH, vcd_parse_def_ignore(), vcd_parse_def_scope(), and vcd_parse_def_var().

Referenced by vcd_parse().

00204   { PROFILE(VCD_PARSE_DEF);
00205 
00206   bool enddef_found = FALSE;  /* If set to true, definition section is finished */
00207   char keyword[256];          /* Holds keyword value */
00208   int  chars_read;            /* Number of characters scanned in */
00209 
00210   while( !enddef_found && (fscanf( vcd, "%s%n", keyword, &chars_read ) == 1) ) {
00211 
00212     assert( chars_read <= 256 );
00213     
00214     if( keyword[0] == '$' ) {
00215 
00216       if( strncmp( "var", (keyword + 1), 3 ) == 0 ) {
00217         vcd_parse_def_var( vcd );
00218       } else if( strncmp( "scope", (keyword + 1), 5 ) == 0 ) {
00219         vcd_parse_def_scope( vcd );
00220       } else if( strncmp( "upscope", (keyword + 1), 7 ) == 0 ) {
00221         db_vcd_upscope();
00222         vcd_parse_def_ignore( vcd );
00223       } else if( strncmp( "enddefinitions", (keyword + 1), 14 ) == 0 ) {
00224         enddef_found = TRUE;
00225         vcd_parse_def_ignore( vcd );
00226       } else {
00227         vcd_parse_def_ignore( vcd );
00228       }
00229 
00230     } else {
00231 
00232       unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Non-keyword located where one should have been \"%s\"", keyword );
00233       assert( rv < USER_MSG_LENGTH );
00234       print_output( user_msg, FATAL, __FILE__, __LINE__ );
00235       Throw 0;
00236 
00237     }
00238   
00239   }
00240 
00241   if( !enddef_found ) {
00242     print_output( "Specified VCD file is not a valid VCD file", FATAL, __FILE__, __LINE__ );
00243     Throw 0;
00244   }
00245 
00246   assert( enddef_found );
00247 
00248   /* Check to see that at least one instance was found */
00249   db_check_dumpfile_scopes();
00250 
00251   PROFILE_END;
00252 
00253 }

static void vcd_parse_def_ignore ( FILE *  vcd  )  [static]

Parses specified file until $end keyword is seen, ignoring all text inbetween.

Parameters:
vcd File handle pointer to opened VCD file

References FALSE, PROFILE, PROFILE_END, and TRUE.

Referenced by vcd_parse_def().

00051   { PROFILE(VCD_PARSE_DEF_IGNORE);
00052 
00053   bool end_seen = FALSE;  /* If set to true, $end keyword was seen */
00054   char token[256];        /* String value of current token */
00055   int  chars_read;        /* Number of characters scanned in */
00056 
00057   while( !end_seen && (fscanf( vcd, "%s%n", token, &chars_read ) == 1) ) {
00058     assert( chars_read <= 256 );
00059     if( strncmp( "$end", token, 4 ) == 0 ) {
00060       end_seen = TRUE;
00061     }
00062   }
00063 
00064   assert( end_seen );
00065 
00066   PROFILE_END;
00067 
00068 }

static void vcd_parse_def_scope ( FILE *  vcd  )  [static]
Exceptions:
anonymous Throw

Parses definition $scope keyword line until $end keyword is seen.

Parameters:
vcd File handle pointer to opened VCD file

References db_set_vcd_scope(), FATAL, print_output(), PROFILE, PROFILE_END, and Throw.

Referenced by vcd_parse_def().

00172   { PROFILE(VCD_PARSE_DEF_SCOPE);
00173 
00174   char type[256];  /* Scope type */
00175   char id[256];    /* Name of scope to change to */
00176 
00177   if( fscanf( vcd, "%s %s $end", type, id ) == 2 ) {
00178 
00179     /* Make sure that we have not exceeded any array boundaries */
00180     assert( strlen( type ) <= 256 );
00181     assert( strlen( id )   <= 256 );
00182     
00183     /* For now we will let any type slide */
00184     db_set_vcd_scope( id );
00185 
00186   } else {
00187 
00188     print_output( "Unrecognized $scope format", FATAL, __FILE__, __LINE__ );
00189     Throw 0;
00190 
00191   }
00192 
00193   PROFILE_END;
00194   
00195 }

static void vcd_parse_def_var ( FILE *  vcd  )  [static]
Exceptions:
anonymous Throw Throw Throw Throw

Parses definition $var keyword line until $end keyword is seen.

Parameters:
vcd File handle pointer to opened VCD file

References db_assign_symbol(), FATAL, print_output(), PROFILE, PROFILE_END, and Throw.

Referenced by vcd_parse_def().

00077   { PROFILE(VCD_PARSE_DEF_VAR);
00078 
00079   char type[256];     /* Variable type */
00080   int  size;          /* Bit width of specified variable */
00081   char id_code[256];  /* Unique variable identifier_code */
00082   char ref[256];      /* Name of variable in design */
00083   char reftmp[256];   /* Temporary variable name */
00084   char tmp[15];       /* Temporary string holder */
00085   int  msb = -1;      /* Most significant bit */
00086   int  lsb = -1;      /* Least significant bit */
00087   int  tmplsb;        /* Temporary LSB if swapping is needed */
00088 
00089   if( fscanf( vcd, "%s %d %s %s %s", type, &size, id_code, ref, tmp ) == 5 ) {
00090 
00091     /* Make sure that we have not exceeded array boundaries */
00092     assert( strlen( type )    <= 256 );
00093     assert( strlen( ref )     <= 256 );
00094     assert( strlen( tmp )     <= 15  );
00095     assert( strlen( id_code ) <= 256 );
00096     
00097     if( strncmp( "real", type, 4 ) == 0 ) {
00098 
00099       msb = 63;
00100       lsb = 0;
00101 
00102     } else {
00103 
00104       if( strncmp( "$end", tmp, 4 ) != 0 ) {
00105 
00106         /* A bit select was specified for this signal, get the size */
00107         if( sscanf( tmp, "\[%d:%d]", &msb, &lsb ) != 2 ) {
00108         
00109           if( sscanf( tmp, "\[%d]", &lsb ) != 1 ) {
00110             print_output( "Unrecognized $var format", FATAL, __FILE__, __LINE__ );
00111             Throw 0;
00112           } else {
00113             msb = lsb;
00114           }
00115 
00116         }
00117 
00118         if( (fscanf( vcd, "%s", tmp ) != 1) || (strncmp( "$end", tmp, 4 ) != 0) ) {
00119           print_output( "Unrecognized $var format", FATAL, __FILE__, __LINE__ );
00120           Throw 0;
00121         }
00122 
00123       } else if( sscanf( ref, "%[a-zA-Z0-9_]\[%s].", reftmp, tmp ) == 2 ) {
00124 
00125         /* This is a hierarchical reference so we shouldn't modify ref -- quirky behavior from VCS */
00126         msb = size - 1;
00127         lsb = 0;
00128 
00129       } else if( sscanf( ref, "%[a-zA-Z0-9_]\[%s]", reftmp, tmp ) == 2 ) {
00130   
00131         strcpy( ref, reftmp );
00132   
00133         if( sscanf( tmp, "%d:%d", &msb, &lsb ) != 2 ) {
00134           if( sscanf( tmp, "%d", &lsb ) != 1 ) {
00135             print_output( "Unrecognized $var format", FATAL, __FILE__, __LINE__ );
00136             Throw 0;
00137           } else {
00138             msb = lsb;
00139           }
00140         }
00141 
00142       } else {
00143 
00144         msb = size - 1;
00145         lsb = 0;
00146 
00147       }
00148 
00149     }
00150 
00151     /* For now we will let any type and size slide */
00152     db_assign_symbol( ref, id_code, msb, lsb );
00153     
00154   } else {
00155 
00156     print_output( "Unrecognized $var format", FATAL, __FILE__, __LINE__ );
00157     Throw 0;
00158   
00159   }
00160 
00161   PROFILE_END;
00162 
00163 }

static void vcd_parse_sim ( FILE *  vcd  )  [static]
Exceptions:
anonymous db_do_timestep db_do_timestep vcd_parse_sim_vector Throw vcd_parse_sim_ignore

Parses all lines that occur in the simulation portion of the VCD file.

Parameters:
vcd File handle of opened VCD file

References db_do_timestep(), db_set_symbol_char(), FALSE, FATAL, print_output(), PROFILE, PROFILE_END, simulate, Throw, TRUE, user_msg, USER_MSG_LENGTH, vcd_parse_sim_real(), and vcd_parse_sim_vector().

Referenced by vcd_parse().

00350   { PROFILE(VCD_PARSE_SIM);
00351 
00352   char   token[4100];                /* Current token from VCD file */
00353   uint64 last_timestep     = 0;      /* Value of last timestamp from file */
00354   bool   use_last_timestep = FALSE;  /* Specifies if timestep has been encountered */
00355   int    chars_read;                 /* Number of characters scanned in */
00356   bool   carry_over        = FALSE;  /* Specifies if last string was too long */
00357   bool   simulate          = TRUE;   /* Specifies if we should continue to simulate */
00358  
00359   while( !feof( vcd ) && (fscanf( vcd, "%4099s%n", token, &chars_read ) == 1) && simulate ) {
00360 
00361     if( chars_read < 4099 ) {
00362     
00363       if( token[0] == '$' ) {
00364 
00365         /* Ignore */
00366 
00367       } else if( (token[0] == 'b') || (token[0] == 'B') ) {
00368 
00369         vcd_parse_sim_vector( vcd, (token + 1) );
00370 
00371       } else if( (token[0] == 'r') || (token[0] == 'R') || carry_over ) {
00372 
00373         vcd_parse_sim_real( vcd, (token + 1) );
00374         carry_over = FALSE;
00375 
00376       } else if( token[0] == '#' ) {
00377 
00378         if( use_last_timestep ) {
00379           simulate = db_do_timestep( last_timestep, FALSE );
00380         }
00381         last_timestep = ato64( token + 1 );
00382         use_last_timestep = TRUE;
00383 
00384       } else if( (token[0] == '0') ||
00385                  (token[0] == '1') ||
00386                  (token[0] == 'x') ||
00387                  (token[0] == 'X') ||
00388                  (token[0] == 'z') ||
00389                  (token[0] == 'Z') ) {
00390 
00391         db_set_symbol_char( token + 1, token[0] );
00392 
00393       } else {
00394 
00395         unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Badly placed token \"%s\"", token );
00396         assert( rv < USER_MSG_LENGTH );
00397         print_output( user_msg, FATAL, __FILE__, __LINE__ );
00398         Throw 0;
00399 
00400       }
00401 
00402     } else {
00403  
00404       carry_over = TRUE;
00405 
00406     }
00407 
00408   }
00409 
00410   /* Simulate the last timestep now */
00411   if( use_last_timestep && simulate ) {
00412     (void)db_do_timestep( last_timestep, FALSE );
00413   }
00414 
00415   PROFILE_END;
00416 
00417 }

static void vcd_parse_sim_ignore ( FILE *  vcd  )  [static]
Exceptions:
anonymous Throw

Reads in symbol from simulation vector line that is to be ignored (unused). Signals an error message if the line is improperly formatted.

Parameters:
vcd File handle of opened VCD file

References FATAL, print_output(), PROFILE, PROFILE_END, and Throw.

00325   { PROFILE(VCD_PARSE_SIM_IGNORE);
00326 
00327   char sym[256];    /* String value of signal symbol */
00328   int  chars_read;  /* Number of characters scanned in */
00329 
00330   if( fscanf( vcd, "%s%n", sym, &chars_read ) != 1 ) {
00331 
00332     print_output( "Bad file format", FATAL, __FILE__, __LINE__ );
00333     Throw 0;
00334 
00335   }
00336   
00337   assert( chars_read <= 256 );
00338 
00339   PROFILE_END;
00340 
00341 }

static void vcd_parse_sim_real ( FILE *  vcd,
char *  value 
) [static]
Exceptions:
anonymous Throw

Reads the next token from the file and calls the appropriate database storage function for this signal change.

Parameters:
vcd File handle of opened VCD file
value String containing value of current signal

References db_set_symbol_string(), FATAL, print_output(), PROFILE, PROFILE_END, and Throw.

Referenced by vcd_parse_sim().

00295   { PROFILE(VCD_PARSE_SIM_REAL);
00296 
00297   char sym[256];    /* String value of signal symbol */
00298   int  chars_read;  /* Number of characters scanned in */
00299 
00300   if( fscanf( vcd, "%s%n", sym, &chars_read ) == 1 ) {
00301 
00302     assert( chars_read <= 256 );
00303 
00304     db_set_symbol_string( sym, value );
00305 
00306   } else {
00307 
00308     print_output( "Bad file format", FATAL, __FILE__, __LINE__ );
00309     Throw 0;
00310 
00311   }
00312 
00313   PROFILE_END;
00314 
00315 }

static void vcd_parse_sim_vector ( FILE *  vcd,
char *  value 
) [static]
Exceptions:
anonymous Throw

Reads the next token from the file and calls the appropriate database storage function for this signal change.

Parameters:
vcd File handle of opened VCD file
value String containing value of current signal

References db_set_symbol_string(), FATAL, print_output(), PROFILE, PROFILE_END, and Throw.

Referenced by vcd_parse_sim().

00264   { PROFILE(VCD_PARSE_SIM_VECTOR);
00265 
00266   char sym[256];    /* String value of signal symbol */
00267   int  chars_read;  /* Number of characters scanned in */
00268 
00269   if( fscanf( vcd, "%s%n", sym, &chars_read ) == 1 ) {
00270 
00271     assert( chars_read <= 256 );
00272     
00273     db_set_symbol_string( sym, value );
00274 
00275   } else {
00276 
00277     print_output( "Bad file format", FATAL, __FILE__, __LINE__ );
00278     Throw 0;
00279 
00280   }
00281 
00282   PROFILE_END;
00283 
00284 }


Variable Documentation

Pointer to the current timestep table array. Please see the file description for how this structure is used.

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.

Pointer to the VCD symbol table. Please see the file description for how this structure is used.

Maintains current number of nodes in the VCD symbol table. This value is used to create the appropriately sized timestep_tab array.

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