yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
verilog_frontend.h File Reference
#include "kernel/yosys.h"
#include "frontends/ast/ast.h"
#include <stdio.h>
#include <stdint.h>
#include <list>
+ Include dependency graph for verilog_frontend.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Namespaces

 VERILOG_FRONTEND
 

Functions

AST::AstNodeVERILOG_FRONTEND::const2ast (std::string code, char case_type=0, bool warn_z=false)
 
std::string frontend_verilog_preproc (std::istream &f, std::string filename, const std::map< std::string, std::string > pre_defines_map, const std::list< std::string > include_dirs)
 
int frontend_verilog_yylex (void)
 
void frontend_verilog_yyerror (char const *fmt,...)
 
void frontend_verilog_yyrestart (FILE *f)
 
int frontend_verilog_yyparse (void)
 
int frontend_verilog_yylex_destroy (void)
 
int frontend_verilog_yyget_lineno (void)
 
void frontend_verilog_yyset_lineno (int)
 

Variables

struct AST::AstNodeVERILOG_FRONTEND::current_ast
 
bool VERILOG_FRONTEND::default_nettype_wire
 
bool VERILOG_FRONTEND::sv_mode
 
std::istream * VERILOG_FRONTEND::lexin
 
YOSYS_NAMESPACE_END int frontend_verilog_yydebug
 

Function Documentation

std::string frontend_verilog_preproc ( std::istream &  f,
std::string  filename,
const std::map< std::string, std::string >  pre_defines_map,
const std::list< std::string >  include_dirs 
)

Definition at line 212 of file preproc.cc.

213 {
214  std::set<std::string> defines_with_args;
215  std::map<std::string, std::string> defines_map(pre_defines_map);
216  int ifdef_fail_level = 0;
217  bool in_elseif = false;
218 
219  output_code.clear();
220  input_buffer.clear();
221  input_buffer_charp = 0;
222 
223  input_file(f, filename);
224  defines_map["__YOSYS__"] = "1";
225 
226  while (!input_buffer.empty())
227  {
228  std::string tok = next_token();
229  // printf("token: >>%s<<\n", tok != "\n" ? tok.c_str() : "NEWLINE");
230 
231  if (tok == "`endif") {
232  if (ifdef_fail_level > 0)
233  ifdef_fail_level--;
234  if (ifdef_fail_level == 0)
235  in_elseif = false;
236  continue;
237  }
238 
239  if (tok == "`else") {
240  if (ifdef_fail_level == 0)
241  ifdef_fail_level = 1;
242  else if (ifdef_fail_level == 1 && !in_elseif)
243  ifdef_fail_level = 0;
244  continue;
245  }
246 
247  if (tok == "`elsif") {
248  skip_spaces();
249  std::string name = next_token(true);
250  if (ifdef_fail_level == 0)
251  ifdef_fail_level = 1, in_elseif = true;
252  else if (ifdef_fail_level == 1 && defines_map.count(name) != 0)
253  ifdef_fail_level = 0, in_elseif = true;
254  continue;
255  }
256 
257  if (tok == "`ifdef") {
258  skip_spaces();
259  std::string name = next_token(true);
260  if (ifdef_fail_level > 0 || defines_map.count(name) == 0)
261  ifdef_fail_level++;
262  continue;
263  }
264 
265  if (tok == "`ifndef") {
266  skip_spaces();
267  std::string name = next_token(true);
268  if (ifdef_fail_level > 0 || defines_map.count(name) != 0)
269  ifdef_fail_level++;
270  continue;
271  }
272 
273  if (ifdef_fail_level > 0) {
274  if (tok == "\n")
275  output_code.push_back(tok);
276  continue;
277  }
278 
279  if (tok == "`include") {
280  skip_spaces();
281  std::string fn = next_token(true);
282  while (1) {
283  size_t pos = fn.find('"');
284  if (pos == std::string::npos)
285  break;
286  if (pos == 0)
287  fn = fn.substr(1);
288  else
289  fn = fn.substr(0, pos) + fn.substr(pos+1);
290  }
291  std::ifstream ff;
292  ff.clear();
293  ff.open(fn.c_str());
294  if (ff.fail() && fn.size() > 0 && fn[0] != '/' && filename.find('/') != std::string::npos) {
295  // if the include file was not found, it is not given with an absolute path, and the
296  // currently read file is given with a path, then try again relative to its directory
297  ff.clear();
298  ff.open(filename.substr(0, filename.rfind('/')+1) + fn);
299  }
300  if (ff.fail() && fn.size() > 0 && fn[0] != '/') {
301  // if the include file was not found and it is not given with an absolute path, then
302  // search it in the include path
303  for (auto incdir : include_dirs) {
304  ff.clear();
305  ff.open(incdir + '/' + fn);
306  if (!ff.fail()) break;
307  }
308  }
309  if (ff.fail())
310  output_code.push_back("`file_notfound " + fn);
311  else
312  input_file(ff, fn);
313  continue;
314  }
315 
316  if (tok == "`define") {
317  std::string name, value;
318  std::map<std::string, int> args;
319  skip_spaces();
320  name = next_token(true);
321  bool here_doc_mode = false;
322  int newline_count = 0;
323  int state = 0;
324  if (skip_spaces() != "")
325  state = 3;
326  while (!tok.empty()) {
327  tok = next_token();
328  if (tok == "\"\"\"") {
329  here_doc_mode = !here_doc_mode;
330  continue;
331  }
332  if (state == 0 && tok == "(") {
333  state = 1;
334  skip_spaces();
335  } else
336  if (state == 1) {
337  if (tok == ")")
338  state = 2;
339  else if (tok != ",") {
340  int arg_idx = args.size()+1;
341  args[tok] = arg_idx;
342  }
343  skip_spaces();
344  } else {
345  if (state != 2)
346  state = 3;
347  if (tok == "\n") {
348  if (here_doc_mode) {
349  value += " ";
350  newline_count++;
351  } else {
352  return_char('\n');
353  break;
354  }
355  } else
356  if (tok == "\\") {
357  char ch = next_char();
358  if (ch == '\n') {
359  value += " ";
360  newline_count++;
361  } else {
362  value += std::string("\\");
363  return_char(ch);
364  }
365  } else
366  if (args.count(tok) > 0)
367  value += stringf("`macro_%s_arg%d", name.c_str(), args.at(tok));
368  else
369  value += tok;
370  }
371  }
372  while (newline_count-- > 0)
373  return_char('\n');
374  // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str());
375  defines_map[name] = value;
376  if (state == 2)
377  defines_with_args.insert(name);
378  else
379  defines_with_args.erase(name);
380  continue;
381  }
382 
383  if (tok == "`undef") {
384  std::string name;
385  skip_spaces();
386  name = next_token(true);
387  // printf("undef: >>%s<<\n", name.c_str());
388  defines_map.erase(name);
389  defines_with_args.erase(name);
390  continue;
391  }
392 
393  if (tok == "`timescale") {
394  skip_spaces();
395  while (!tok.empty() && tok != "\n")
396  tok = next_token(true);
397  if (tok == "\n")
398  return_char('\n');
399  continue;
400  }
401 
402  if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) {
403  std::string name = tok.substr(1);
404  // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str());
405  std::string skipped_spaces = skip_spaces();
406  tok = next_token(false);
407  if (tok == "(" && defines_with_args.count(name) > 0) {
408  int level = 1;
409  std::vector<std::string> args;
410  args.push_back(std::string());
411  while (1)
412  {
413  tok = next_token(true);
414  if (tok == ")" || tok == "}" || tok == "]")
415  level--;
416  if (level == 0)
417  break;
418  if (level == 1 && tok == ",")
419  args.push_back(std::string());
420  else
421  args.back() += tok;
422  if (tok == "(" || tok == "{" || tok == "[")
423  level++;
424  }
425  for (int i = 0; i < GetSize(args); i++)
426  defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i];
427  } else {
428  insert_input(tok);
429  insert_input(skipped_spaces);
430  }
431  insert_input(defines_map[name]);
432  continue;
433  }
434 
435  output_code.push_back(tok);
436  }
437 
438  std::string output;
439  for (auto &str : output_code)
440  output += str;
441 
442  output_code.clear();
443  input_buffer.clear();
444  input_buffer_charp = 0;
445 
446  return output;
447 }
static std::string next_token(bool pass_newline=false)
Definition: preproc.cc:96
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
static std::string skip_spaces()
Definition: preproc.cc:80
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
static void return_char(char ch)
Definition: preproc.cc:47
static size_t input_buffer_charp
Definition: preproc.cc:45
static char next_char()
Definition: preproc.cc:64
static std::list< std::string > input_buffer
Definition: preproc.cc:44
static void insert_input(std::string str)
Definition: preproc.cc:55
static void input_file(std::istream &f, std::string filename)
Definition: preproc.cc:196
static YOSYS_NAMESPACE_BEGIN std::list< std::string > output_code
Definition: preproc.cc:43

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void frontend_verilog_yyerror ( char const *  fmt,
  ... 
)

Definition at line 364 of file verilog_frontend.cc.

365 {
366  va_list ap;
367  char buffer[1024];
368  char *p = buffer;
369  p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ",
371  va_start(ap, fmt);
372  p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
373  va_end(ap);
374  p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
375  YOSYS_NAMESPACE_PREFIX log_error("%s", buffer);
376  exit(1);
377 }
#define YOSYS_NAMESPACE_PREFIX
Definition: yosys.h:101
void log_error(const char *format,...)
Definition: log.cc:204
int frontend_verilog_yyget_lineno(void)
std::string current_filename
Definition: ast.cc:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int frontend_verilog_yyget_lineno ( void  )

Get the current line number.

Definition at line 2805 of file verilog_lexer.cc.

2806 {
2807 
2809 }
int frontend_verilog_yylineno

+ Here is the caller graph for this function:

int frontend_verilog_yylex ( void  )
int frontend_verilog_yylex_destroy ( void  )

Definition at line 2912 of file verilog_lexer.cc.

2913 {
2914 
2915  /* Pop the buffer stack, destroying each element. */
2916  while(YY_CURRENT_BUFFER){
2920  }
2921 
2922  /* Destroy the stack itself. */
2924  (yy_buffer_stack) = NULL;
2925 
2926  /* Reset the globals. This is important in a non-reentrant scanner so the next time
2927  * frontend_verilog_yylex() is called, initialization will occur. */
2928  yy_init_globals( );
2929 
2930  return 0;
2931 }
#define YY_CURRENT_BUFFER
static YY_BUFFER_STATE * yy_buffer_stack
static int yy_init_globals(void)
#define NULL
void frontend_verilog_yypop_buffer_state(void)
void frontend_verilog_yy_delete_buffer(YY_BUFFER_STATE b)
#define YY_CURRENT_BUFFER_LVALUE
void frontend_verilog_yyfree(void *)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int frontend_verilog_yyparse ( void  )

+ Here is the caller graph for this function:

void frontend_verilog_yyrestart ( FILE *  input_file)

Immediately switch to a different input stream.

Parameters
input_fileA readable stream.
Note
This function does not reset the start condition to INITIAL .

Definition at line 2425 of file verilog_lexer.cc.

2426 {
2427 
2428  if ( ! YY_CURRENT_BUFFER ){
2432  }
2433 
2436 }
#define YY_CURRENT_BUFFER
FILE * frontend_verilog_yyin
static void frontend_verilog_yy_init_buffer(YY_BUFFER_STATE b, FILE *file)
#define YY_BUF_SIZE
static void frontend_verilog_yy_load_buffer_state(void)
static void frontend_verilog_yyensure_buffer_stack(void)
YY_BUFFER_STATE frontend_verilog_yy_create_buffer(FILE *file, int size)
static void input_file(std::istream &f, std::string filename)
Definition: preproc.cc:196
#define YY_CURRENT_BUFFER_LVALUE

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void frontend_verilog_yyset_lineno ( int  line_number)

Set the current line number.

Parameters
line_number

Definition at line 2848 of file verilog_lexer.cc.

2849 {
2850 
2851  frontend_verilog_yylineno = line_number;
2852 }
int frontend_verilog_yylineno

+ Here is the caller graph for this function:

Variable Documentation

YOSYS_NAMESPACE_END int frontend_verilog_yydebug