预处理就是处理define、include、ifdef等,在Icarus Verilog里是由ivlpp来处理的。在Icarus Verilog里,ivlpp是单独的程序,与主程序分开,可以减轻主程序的工作量。
ivlpp接收待处理文件,处理结束后输出结果到standard output。在driver(iverilog的入口程序)里,处理完命令行参数后,通过system("ivlpp xx xx")来自动调用。
ivlpp
\ globals.h
\ lexor.lex
\ main.c
\ Makefile.in
详细处理过程
首先用flex来进行关键字(include|define|undef|ifdef|ifndef|else|elseif|endif)扫描,然后把信息存到struct include_stack_t、ifdef_stack_t、define_t的结构体里,形成文件列表、define列表。
然后用函数逐个处理,如包括文件、宏展开。相关的函数如下:
static void def_start(void);
static void def_add_arg(void);
static void def_finish(void);
static void def_undefine(void);
static void do_define(void);
static int def_is_done(void);
static void def_continue(void);
static int is_defined(const char*name);
static int macro_needs_args(const char*name);
static void macro_start_args(void);
static void macro_add_to_arg(int is_whitespace);
static void macro_finish_arg(void);
static void do_expand(int use_args);
static const char* do_magic(const char*name);
static const char* macro_name(void);
static void include_filename(void);
static void do_include(void);
static int load_next_input(void);