这个事情说起来就有点诡异了,我们解释一下
--exe
,完成到生成全部的源文件,以及获取生成可执行文件的makefile文件这一步verilator --cc --exe Top.v main.cpp
Top.v main.cpp
,这里的保持不变,是指其时间戳保持不变VTop.mk
文件,是本次测试唯一的变量,我们接下来看一看假设,我们已经运行了指令verilator --cc --exe Top.v main.cpp
,生成了相关的文件。
接下来:
首先,我们运行
ls obj_dir/ --full-time > 1.txt
把测试前的文件时间戳存储起来
total 128
-rw-rw-r-- 1 jht jht 19595 2022-04-17 11:44:49.941869470 +0800 VTop___024root.cpp
-rw-rw-r-- 1 jht jht 1846 2022-04-17 11:44:49.941869470 +0800 VTop___024root.h
-rw-rw-r-- 1 jht jht 11606 2022-04-17 11:44:49.941869470 +0800 VTop___024root__Slow.cpp
...
这里展示一小部分,太多了没必要展示。
接下来,我们再次运行verilator --cc --exe Top.v main.cpp
,然后运行ls obj_dir/ --full-time > 2.txt
,把新的时间戳存储起来。
紧接着,使用colordiff 1.txt 2.txt
进行对比,没有任何输出,说明前后文件时间戳完全一样,这意味着,第二次运行的指令,没有导致生成结果的更新!
要知道,生成的结果
而第二次没有更新,没有重新编译和拷贝,证明verilator本身是有检测机制的,不会每次无脑编译更新。
接下来,做一个新的测试。
假设,我们已经运行了指令verilator --cc --exe Top.v main.cpp
,生成了相关的文件。
ls obj_dir/ --full-time > 1.txt
VTop.mk
文件,比如给其任意位置,加一个注释,运行sed -i "1 i # test" obj_dir/VTop.mk
或者手动修改该文件verilator --cc --exe Top.v main.cpp
ls obj_dir/ --full-time > 2.txt
colordiff 1.txt 2.txt
进行对比神奇的事情发生了!,所有的源文件,都被修改了时间戳,也就是说这些源文件都是新生成或者新拷贝的!
2,16c2,16
< -rw-rw-r-- 1 jht jht 19595 2022-04-17 11:52:02.256126245 +0800 VTop___024root.cpp
< -rw-rw-r-- 1 jht jht 1846 2022-04-17 11:52:02.252126217 +0800 VTop___024root.h
< -rw-rw-r-- 1 jht jht 11606 2022-04-17 11:52:02.256126245 +0800 VTop___024root__Slow.cpp
...
---
> -rw-rw-r-- 1 jht jht 19595 2022-04-17 11:52:16.824228142 +0800 VTop___024root.cpp
> -rw-rw-r-- 1 jht jht 1846 2022-04-17 11:52:16.824228142 +0800 VTop___024root.h
> -rw-rw-r-- 1 jht jht 11606 2022-04-17 11:52:16.824228142 +0800 VTop___024root__Slow.cpp
...
这里只展示一部分,事实上,是所有的源文件都更新了。
另外经过测试,给mk文件加个空行也可以达到该效果。
这就意味着什么呢……至少
这里,同样是命令verilator --cc --exe Top.v main.cpp
,我们单独修改Top.v
,再查看前后对比结果。
发现也是全部更新源文件,和上面一样。
仅仅修改main.cpp
因为cpp文件没有被拷贝进去,而是直接编译的外面的源文件。
obj_dir
中任意一个文件(生成的源文件)随便修改一个文件,前后对比,发现仍然是更新全部源文件。
经过这么多的测试,你就应该明白了,对于verilator的--cc --exe
阶段,也就是生成可执行文件之前的阶段,无论你是修改命令中给出的源文件(指Verilog源文件,c/cpp不算),还是修改生成之后的任意一个文件,都会导致下一次重新运行该命令的时候,全部重新编译和更新。
注意,修改生成的文件,是指的运行VTop.mk
之前的那些文件,运行make之后生成内些文件不会跟着更新,它们的更新依靠的是make规则。
好了,这个在文档没有找到,估计只能在源码中找了,先不管,反正测试结果就是这样!
我们看一下,这个特性能够让我们有什么应用呢?
obj_dir
文件夹中源文件的,外部文件它是不管的!.o
文件,这个文件不会被放在obj_dir
文件夹中,只是在VTop.mk
中提供外部.o
文件的路径,以供链接使用.o
文件,按照生成规则来说,verilator的不知道这件事的,它会默认你的.o
文件是一直不变的,这就意味着,你需要额外的规则来改变这件事.c
文件到.o
文件,但是verilator不知道这件事,我们有两种方法
VTop.mk
随便编辑一下,下一次编译一定会全部更新的。但是这样似乎不太好…….o
文件是否更新,如果更新,则可以
VTop
可执行文件,重新进行链接即可。这种方式是可取的,如果其他的都没变的话,只是外部的.o
文件改变,只需要重新链接就可以加粗部分,是提倡采取的方案。
下面是提供的复杂工程的示例
simulate
├── csrc # c/cpp 源文件和可重定位目标文件
│ ├── build # 由 .c 文件生成,.o文件提供给verilator
│ │ ├── memory
│ │ │ └── mem.o
│ │ └── monitor
│ │ ├── monitor.o
│ │ └── sdb
│ │ └── sdb.o
│ ├── include # 头文件
│ │ ├── common.h
│ │ ├── main.h
│ │ └── mem.h
│ ├── main.cpp # 提供给verilator的cpp文件
│ ├── Makefile # 生成 build 的规则
│ ├── memory # c 源文件
│ │ └── mem.c
│ ├── monitor
│ │ ├── monitor.c
│ │ └── sdb
│ │ └── sdb.c
│ └── utils
├── Makefile # verilator编译和生成规则
└── obj_dir # verilator生成目录
# 备注:Verilog文件在其他路径,可由verilator来指定位置和文件