#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] |
symtable * | vcd_symtab |
int | vcd_symtab_size |
symtable ** | timestep_tab |
void vcd_parse | ( | const char * | vcd_file | ) |
Parses specified VCD file, storing information into database.
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.
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] |
anonymous | Throw Throw Throw vcd_parse_def_scope vcd_parse_def_var |
Parses all definition information from specified file.
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.
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] |
anonymous | Throw |
Parses definition $scope keyword line until $end keyword is seen.
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] |
anonymous | Throw Throw Throw Throw |
Parses definition $var keyword line until $end keyword is seen.
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] |
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.
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] |
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.
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] |
anonymous | Throw |
Reads the next token from the file and calls the appropriate database storage function for this signal change.
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] |
anonymous | Throw |
Reads the next token from the file and calls the appropriate database storage function for this signal change.
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 }
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.
int vcd_symtab_size |
Maintains current number of nodes in the VCD symbol table. This value is used to create the appropriately sized timestep_tab array.