File: parse.c

package info (click to toggle)
covered 0.7.10-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 9,040 kB
  • sloc: ansic: 48,809; yacc: 11,650; xml: 8,838; tcl: 7,698; sh: 3,925; lex: 2,240; makefile: 362; perl: 329
file content (310 lines) | stat: -rw-r--r-- 9,878 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 Copyright (c) 2006-2010 Trevor Williams

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with this program;
 if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*!
 \file     parse.c
 \author   Trevor Williams  (phase1geo@gmail.com)
 \date     11/27/2001
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "binding.h"
#include "db.h"
#include "defines.h"
#include "fsm_var.h"
#include "fst.h"
#include "info.h"
#include "link.h"
#include "lxt.h"
#include "parse.h"
#include "parser_misc.h"
#include "race.h"
#include "score.h"
#include "sim.h"
#include "stmt_blk.h"
#include "util.h"
#include "vcd.h"


extern void reset_lexer( str_link* file_list_head );
extern int VLparse();

extern str_link* use_files_head;
extern str_link* modlist_head;
extern str_link* modlist_tail;
extern char      user_msg[USER_MSG_LENGTH];
extern isuppl    info_suppl;
extern bool      flag_check_races;
extern sig_range curr_prange;
extern sig_range curr_urange;
extern bool      instance_specified;
extern char*     top_module;
extern char*     ppfilename;
extern bool      debug_mode;
extern char*     dumpvars_file;

/*!
 \return Returns the number of characters read from this line.

 Reads from specified file, one character at a time, until either a newline
 or EOF is encountered.  Returns the read line and the number of characters
 stored in the line.  No newline character is added to the line.
*/
int parse_readline(
  FILE* file,  /*!< Pointer to file to read */
  char* line,  /*!< Read line from specified file */
  int   size   /*!< Maximum number of characters that can be stored in line */
) { PROFILE(PARSE_READLINE);

  int i = 0;  /* Loop iterator */

  while( (i < (size - 1)) && !feof( file ) && ((line[i] = fgetc( file )) != '\n') ) {
    i++;
  }

  if( !feof( file ) ) {
    line[i] = '\0';
  }

  if( i == size ) {
    unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Line too long.  Must be less than %d characters.", size );
    assert( rv < USER_MSG_LENGTH );
    print_output( user_msg, FATAL, __FILE__, __LINE__ );
  }

  PROFILE_END;

  return( !feof( file ) );

}

/*!
 \throws anonymous fsm_var_bind race_check_modules Throw bind_perform db_write

 Resets the lexer and parses all Verilog files specified in use_files list.
 After all design files are parsed, their information will be appropriately
 stored in the associated lists.
*/
void parse_design(
  const char* top,       /*!< Name of top-level module to score */
  const char* output_db  /*!< Name of output directory for generated scored files */
) { PROFILE(PARSE_DESIGN);

  Try {

    (void)str_link_add( strdup_safe( top ), &modlist_head, &modlist_tail );

    if( use_files_head != NULL ) {

      int parser_ret;

      /* Initialize lexer with first file */
      reset_lexer( use_files_head );

      Try {

        /* Parse the design -- if we catch an exception, remove the temporary ppfilename */
        parser_ret = VLparse();

        if( (parser_ret != 0) || (error_count > 0) ) {
          print_output( "Error in parsing design", FATAL, __FILE__, __LINE__ );
          Throw 0;
        }

      } Catch_anonymous {
        (void)unlink( ppfilename );
        parser_dealloc_sig_range( &curr_urange, FALSE );
        parser_dealloc_sig_range( &curr_prange, FALSE );
        Throw 0;
      }
     
      /* Deallocate any memory in curr_range variable */
      parser_dealloc_sig_range( &curr_urange, FALSE );
      parser_dealloc_sig_range( &curr_prange, FALSE );

#ifdef DEBUG_MODE
      if( debug_mode ) {
        print_output( "========  Completed design parsing  ========\n", DEBUG, __FILE__, __LINE__ );
      }
#endif

      /* Check to make sure that the -t and -i options were specified correctly */
      if( db_check_for_top_module() ) {
        if( instance_specified ) {
          unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Module specified with -t option (%s) is a top-level module.", top_module );
          assert( rv < USER_MSG_LENGTH );
          print_output( user_msg, FATAL, __FILE__, __LINE__ );
          print_output( "The -i option should not have been specified", FATAL_WRAP, __FILE__, __LINE__ );
          Throw 0;
        }
      } else {
        if( !instance_specified ) {
          unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Module specified with -t option (%s) is not a top-level module.", top_module );
          assert( rv < USER_MSG_LENGTH );
          print_output( user_msg, FATAL, __FILE__, __LINE__ );
          print_output( "The -i option must be specified to provide the hierarchy to the module specified with", FATAL_WRAP, __FILE__, __LINE__ );
          print_output( "the -t option.", FATAL_WRAP, __FILE__, __LINE__ );
          Throw 0;
        }
      }

      /* Perform all signal/expression binding */
      bind_perform( FALSE, 0 );
      fsm_var_bind();
  
      /* Perform race condition checking */
      if( flag_check_races ) {
        print_output( "\nChecking for race conditions...", NORMAL, __FILE__, __LINE__ );
        race_check_modules();
      } else {
        print_output( "The -rI option was specified in the command-line, causing Covered to skip race condition", WARNING, __FILE__, __LINE__ );
        print_output( "checking; therefore, coverage information may not be accurate if actual race conditions", WARNING_WRAP, __FILE__, __LINE__ );
        print_output( "do exist.  Proceed at your own risk!", WARNING_WRAP, __FILE__, __LINE__ );
      }

      /* Remove all statement blocks that cannot be considered for coverage */
      stmt_blk_remove();

#ifdef DEBUG_MODE
      if( debug_mode ) {
        print_output( "========  Completed race condition checking  ========\n", DEBUG, __FILE__, __LINE__ );
      }
#endif

    } else {

      print_output( "No Verilog input files specified", FATAL, __FILE__, __LINE__ );
      Throw 0;

    }

    /* Output the dumpvars module, if specified. */
    if( dumpvars_file != NULL ) {
      unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "Outputting dumpvars file %s...", dumpvars_file );
      assert( rv < USER_MSG_LENGTH );
      print_output( user_msg, NORMAL, __FILE__, __LINE__ );
      score_generate_top_dumpvars_module( dumpvars_file );
    }

    /* Write contents to baseline database file. */
    db_write( output_db, TRUE, TRUE );

  } Catch_anonymous {
    fsm_var_cleanup();
    sim_dealloc();
    db_close();
    Throw 0;
  }

  /* Deallocate simulator stuff */
  sim_dealloc();

  /* Close database */
  db_close();

#ifdef DEBUG_MODE
  if( debug_mode ) {
    unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "========  Design written to database %s successfully  ========\n\n", output_db );
    assert( rv < USER_MSG_LENGTH );
    print_output( user_msg, DEBUG, __FILE__, __LINE__ );
  }
#endif

  PROFILE_END;

}

/*!
 \throws anonymous db_do_timestep Throw vcd_parse bind_perform db_read lxt_parse db_write

 Reads in specified CDD database file, reads in specified dumpfile in the specified format,
 performs re-simulation and writes the scored design back to the specified CDD database file
 for merging or reporting.
*/
void parse_and_score_dumpfile(
  const char* db,         /*!< Name of output database file to generate */
  const char* dump_file,  /*!< Name of dumpfile to parse for scoring */
  int         dump_mode   /*!< Type of dumpfile being used (see \ref dumpfile_fmt for legal values) */
) { PROFILE(PARSE_AND_SCORE_DUMPFILE);

  assert( dump_file != NULL );

  Try {

#ifdef DEBUG_MODE
    if( debug_mode ) {
      unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "========  Reading in database %s  ========\n", db );
      assert( rv < USER_MSG_LENGTH );
      print_output( user_msg, DEBUG, __FILE__, __LINE__ );
    }
#endif

    /* Read in contents of specified database file */
    (void)db_read( db, READ_MODE_NO_MERGE );
  
    /* Bind expressions to signals/functional units */
    bind_perform( TRUE, 0 );

    /* Add static values to simulator */
    sim_initialize();

#ifdef DEBUG_MODE
    if( debug_mode ) {
      unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "========  Reading in VCD dumpfile %s  ========\n", dump_file );
      assert( rv < USER_MSG_LENGTH );
      print_output( user_msg, DEBUG, __FILE__, __LINE__ );
    }
#endif
  
    /* Perform the parse */
    switch( dump_mode ) {
      case DUMP_FMT_VCD :  vcd_parse( dump_file );  break;
      case DUMP_FMT_LXT :  lxt_parse( dump_file );  break;
      case DUMP_FMT_FST :  fst_parse( dump_file );  break;
      default           :  assert( (dump_mode == DUMP_FMT_VCD) || (dump_mode == DUMP_FMT_LXT) || (dump_mode == DUMP_FMT_FST) );
    }
    
    /* Flush any pending statement trees that are waiting for delay */
    (void)db_do_timestep( 0, TRUE );

#ifdef DEBUG_MODE
    if( debug_mode ) {
      unsigned int rv = snprintf( user_msg, USER_MSG_LENGTH, "========  Writing database %s  ========\n", db );
      assert( rv < USER_MSG_LENGTH );
      print_output( user_msg, DEBUG, __FILE__, __LINE__ );
    }
#endif

    /* Indicate that this CDD contains scored information */
    info_suppl.part.scored = 1;

    /* Write contents to database file */
    db_write( db, FALSE, FALSE );

  } Catch_anonymous {
    sim_dealloc();
    Throw 0;
  }

  /* Deallocate simulator stuff */
  sim_dealloc();

  PROFILE_END;

}