数字IC中的Makefile简明教程

1.Makefile可以做什么?

       在ic设计和验证中,脚本的使用会大大提高办公效率,编写脚本是一个一劳永逸的事,能够免除你每次仿真重复的输入相同的命令,有了脚本以后你只需要简单的执行脚本命令即可。常用的脚本有perl,tcl,shell,makefile等,下面主要介绍一下makefile的简单使用。

Makefile可以根据指定的依赖规则和文件是否有修改来执行命令。常用来编译软件源代码,只需要重新编译修改过的文件,使得编译速度大大加快。

2.Makefile的基本格式

                 2.1目标:依赖

                           命令

目标是要生成的结果,依赖是生成结果需要的源文件和上一步骤的结果,命令是当目标不存在或者依赖更新时执行的命令。注意命令前必须用tab键来缩进,不可以用空格。

示例一:
 

simv: tb.sv dut.v

    vcs -full64 -sverilog +v2k -debug_all +notimingcheck +nospecify tb.sv dut.v

这个例子中,simv是目标,是我们要生成的仿真执行文件。tb.sv和dut.v是依赖,执行命令前会先检查tb.sv和dut.v是否存在,以及是否有修改。当依赖文件有修改时,或者目标不存在时,则执行命令vcs -full64 -sverilog +v2k -debug_all +notimingcheck +nospecify tb.sv dut.v来生成simv。

2.2伪目标

有时候目标并不是真实要生成的文件,比如我们要用Makefile调用simv来仿真,并不存在一个目标文件,这种情况我们称之为伪目标PHONY。伪目标是仿真经常使用的makefile写法

 

示例二:

.PHONY sim

sim: simv

    ./simv -xxx

这样,我们在terminal里就可以用make sim来调用仿真命令。

这个例子中,sim并不是要生成的结果文件,而只是我们给操作起的一个名字。由于伪目标总是不存在,所以命令也一定会重新执行,即使simv没有修改。

我们常常在Makefile的开头来用.PHONY显式指明伪目标。

2.3默认目标

如果我们只是敲make(后面不跟目标),那么将调用Makefile里的第一个目标。那么我们为了防止出错通常把第一个目标定义成all(执行完整的流程)或者help(显示帮助菜单)。我更倾向于后者,可以帮助我们回忆如何使用Makefile脚本。

示例三:

.PHONY help sim

help:

    echo "make help"

    echo "make simv to compile"

    echo "make sim to run simulation"

simv: tb.sv dut.v

    vcs -full64 -sverilog tb.sv dut.v

sim:

    ./simv -xxx

这样,当我们不记得如何使用Makefile的时候,直接敲make就会有使用帮助菜单。另外,我们还可以看到,一个目标后面可以执行多条命令,比如这里的三条echo命令。

2.4隐藏回显

在执行命令前,make会先回显命令(就是打印出命令)。上面的make help会输出:

echo "make help"

make help

echo "make simv to compile"

make simv to compile

echo "make sim to run simulation"

make sim to run simulation

看起来有点重复了。在命令前加@可以关闭回显示,这正是我们需要的。改进过的Makefile如示例五。

示例四

.PHONY help

help:

    @echo "make help"

    @echo "make simv to compile"

    @echo "make sim to run simulation"

2.5makefile内定义变量

当源文件比较多,且常需要增减,我们可以把依赖定义成一个变量,放成文件开头,如下。

示例五:

tbfile := tb.sv env_pkg.sv test_pkg.sv

rtlfile := dut.v a.v b.v c.v

simv: $(tbfile) $(rtlfile)

vcs -full64 -sverilog $(tbfile) $(rtlfile)

当要增减文件时,只需要修改文件开头即可。

2.6调用shell命令

如果rtl文件太多,还可以在Makefile里调用shell命令来帮助生成。如下面的例子:

示例六:

tbfile := $(shell ls *.sv)

rtlfile := $(shell find rtl -name "*.v")

simv: $(tbfile) ($rtlfile)

    vcs -full64 -sverilog $(tbfile) $(rtlfile)

例中的tb和rtl文件写两遍,是不是有点麻烦。我们最好能简化一下。在Makefile中有几个特殊变量,如$@表示目标,$^表示依赖。所以示例中的命令可以简化成:

simv: $(tbfile) $(rtlfile)

vcs -full64 -sverilog $^

学到到这里你已经可以写出大部分的Makefile脚本了。

2.7为makefile增加选项

但我们还需要进一步学习两个重要功能:选项和目录递归

我们常需要在仿真时提供一些选项,比如testcase名,是否是post仿真,是否要dump波形。那么怎么实现呢?其实Makefile允许从命令行提供额外的变量,格式为OPTION=value。如下面的例子,假设有三个选项,TC、POST、DUMP:

示例七:

ifeq ($(POST),1)

SRC := "netlist.v"

else

SRC := "rtl.v"

endif


ifeq ($(DUMP),1)

DUMP_DEF := "+define+DUMP"

else

DUMP_DEF := ""

endif


sim:

@echo "vcs -full64 -sverilog $(SRC) $(DUMP_DEF) +UVM_TESTNAME=$(TC)"

那么,使用时就可以通过命令行控制选项开关:

make sim TC=basic_test

make sim TC=basic_test POST=1

make sim TC=basic_test DUMP=1

make sim TC=basic_test POST=1 DUMP=1

2.8makefile的大杀器:目录递归

另一个重要功能是目录递归,目录递归有一个典型的应用:make clean。在顶层目录里make clean时,将会自动调用子目录的make clean。这个怎么实现呢?看下面的例子:

示例八:

./Makefile

clean:

    rm -f *~

    make -C a clean

    make -C b clean

./a/Makefile

clean:

    rm -f *~

./b/Makefile

clean:

    rm -f *~

    make -C c clean

./b/c/Makefile

clean:

    rm -f *~

我们看到一个make -C subdir clean,就是说可以通过-C来把目标clean传递给子目录,相当于在Makefile里调用了另一个Makefile。这样在顶到make clean时,将自动递归到所有的子目录。

2.9Makefile的引用与复用

最后还有一点,我们也会经常遇到,把共用的Makefile脚本写到common.mk,然后再include common.mk,这样可以让Makefile看起来更简洁。

与IC Flow的联系

到这里,学了这么多,你已经可以写一些复杂的Makefile了。但重在应用,在IC设计里,我们常常用Makefile串起多个工具,实现完整的流程。下面是一个启发型的例子。

示例9:
 

.PHONY help clean rtl lint sim syn lec pr pt lvs

help:

    @echo "make help"

clean:   

    rm -rf *~ *.log *.fsdb csrc simv* ...

    make -C xxx clean

rtl:

    python3 ...

lint:

    sg_shell/nLint ...

sim:

    vcs/irun ...

syn:

    dc_shell -64bit -topographical -f run_syn.tcl | tee log/syn.log

lec:

    fm_shell/lec ...

pt:

    pt_shell ...

pr:

    innovus/icc ...

lvs:

    calibre ...

3.vcs仿真简单makefile示例

.PHONY: com  cov  clean debug  sim dve

OUTPUT = simv_asyn_fifo
ALL_DEFINE = +define+DUMP_VPD

# Code coverage command 
#CM = -cm line+cond+fsn+branch+tql
CM = -cm line+cond+branch
CM_NAME = -cm_name $(OUTPUT)
CM_DIR = -cm_dir ./$(OUTPUT).vpd

#vpd file name 
VPD_NAME = +vpdfile+$(OUTPUT).vpd

#Comppile command 
#VCS = vcs -sverilog  +v2k      \
	-debug_all				 \
	+notimingcheck				 \
	+nospecify				 \
	+vcs+flush+all				 \
	+vpdfile+$(OUTPUT).vpd			\
	$(CM)					 \
	$(CM_NAME)				 \
	$(CM_DIR)				 \
	$(ALL_DEFINE)				 \
	-o  $(OUTPUT)				 \
	-l  compile.log	                         \
         -f file_list.f
          
	
#VCS = vcs -sverilog  +v2k      \
	-debug_all				 \
	+notimingcheck				 \
	+nospecify				 \
	+vcs+flush+all				 \
	$(ALL_DEFINE)				 \
   	$(VPD_NAME)				 \
	-o  $(OUTPUT)				 \
	-l  compile.log                \
        -f file_list.f		           
        	

# simulation  command 	
#SIM = ./$(OUTPUT)		\
	$(CM)  $(CM_NAME) $(CM_DIR)	\
        -l $(OUTPUT).log		\
	 +vpdfile+$(OUTPUT).vpd  
        
 
#SIM = ./$(OUTPUT)		\
	$(VPD_NAME)			\
	-l $(OUTPUT).log

#CLEAN=./clean
#start compile 
com:
	$(VCS) 

#start simulation 
sim:
	$(SIM)

#start dve show 
dve:	
	dve  -vpd  $(OUTPUT).vpd  &

#show the coverage 
cov:
	dve  -covdir *vdb &
debug:
	dve -vpd  $(OUTPUT).vpd &

#start clean 
clean:
	rm -rf ./csrc   *daidir   ./csrc   *.log  *.vpd   *.vdb  simv*  *.key   *race.out  vc_hdrs.h    DVEfiles  sim*  compile*   *.fsdb  

  • 22
    点赞
  • 181
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Makefile 是一种用于构建和管理软件项目的工具。它通常用于编译源代码、链接库文件以及执行其他编译任务。下面是一个简单的 Makefile 教程,介绍了如何编写一个基本的 Makefile。 一个典型的 Makefile 包含以下几个部分: 1. 定义变量 (Variables):可以为命令、文件名、目录等定义变量,使得 Makefile 更加灵活。例如,可以定义变量 CC 表示编译器,可以定义变量 CFLAGS 表示编译选项。 2. 定义目标 (Targets):目标是 Makefile 的任务,可以是编译源代码、生成可执行文件等。目标由依赖关系和要执行的命令组成。例如,定义目标 all,它依赖于源代码文件,执行编译命令将源代码编译为可执行文件。 3. 定义依赖关系 (Dependencies):依赖关系指示了哪些文件影响了目标的构建。当依赖文件发生变化时,Make 会重新构建目标。依赖关系写在目标的下一行,并使用 tab 键缩进。 4. 定义命令 (Commands):命令是构建目标的具体步骤。它们可以是编译、链接、复制文件等。命令写在依赖关系的下一行,并使用 tab 键缩进。 5. 定义伪目标 (Phony Targets):伪目标是用来表示某些任务的,它们不对应任何文件。伪目标总是会被执行,而不管是否已经存在文件与之同名。例如,定义伪目标 clean,用于删除生成的文件。 编写一个简单的 Makefile 如下所示: ```makefile # 定义变量 CC = gcc CFLAGS = -Wall # 定义目标和依赖关系 all: main.o utils.o $(CC) $(CFLAGS) -o myprogram main.o utils.o # 定义命令 main.o: main.c utils.h $(CC) $(CFLAGS) -c main.c utils.o: utils.c utils.h $(CC) $(CFLAGS) -c utils.c # 定义伪目标 clean: rm -f myprogram *.o ``` 以上 Makefile 将根据源文件 main.c 和 utils.c 生成一个名为 myprogram 的可执行文件。make all 命令将会执行编译和链接过程,生成最终的可执行文件。make clean 命令将会删除生成的文件。 希望这个简单的 Makefile 教程能够帮助你理解 Makefile 的基本用法。当然,Makefile 还有更多高级用法和选项,可以根据具体需求和项目的复杂度进行进一步学习和探索。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值