verilator编译 更新文件的规则

本文请读者【直接关闭】,我后面的实践结果似乎和本文的实践结果不一样,真是见鬼了!我不知道发生了什么,还没有来得及进一步校验!

在其他文件不变的前提下,如果即将生成的mk文件和已有的mk文件不一样,就更新全部的源文件

这个事情说起来就有点诡异了,我们解释一下

  1. 我们只使用--exe,完成到生成全部的源文件,以及获取生成可执行文件的makefile文件这一步
  2. 编译的命令保持不变,例如 verilator --cc --exe Top.v main.cpp
  3. 命令中提及的文件全都保持不变,例如Top.v main.cpp,这里的保持不变,是指其时间戳保持不变
  4. 对于生成的VTop.mk文件,是本次测试唯一的变量,我们接下来看一看
测试一:不改变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 进行对比,没有任何输出,说明前后文件时间戳完全一样,这意味着,第二次运行的指令,没有导致生成结果的更新!

要知道,生成的结果

  1. 是从外面其他文件(c/cpp)拷贝过来的
  2. 是编译Verilog文件生成的

而第二次没有更新,没有重新编译和拷贝,证明verilator本身是有检测机制的,不会每次无脑编译更新

测试2:修改mk文件

接下来,做一个新的测试。

假设,我们已经运行了指令verilator --cc --exe Top.v main.cpp,生成了相关的文件。

  1. 运行ls obj_dir/ --full-time > 1.txt
  2. 修改VTop.mk文件,比如给其任意位置,加一个注释,运行sed -i "1 i # test" obj_dir/VTop.mk或者手动修改该文件
  3. 再次运行verilator --cc --exe Top.v main.cpp
  4. 运行ls obj_dir/ --full-time > 2.txt
  5. 使用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会检测,当前命令生成的mk文件和已有的mk文件是否有不同,如果不同,就重新生成和更新全部源文件。
实验3:仅修改Verilog文件

这里,同样是命令verilator --cc --exe Top.v main.cpp,我们单独修改Top.v,再查看前后对比结果。

发现也是全部更新源文件,和上面一样。

实验4:仅修改cpp文件

仅仅修改main.cpp

NOTE:不会更新!

因为cpp文件没有被拷贝进去,而是直接编译的外面的源文件。

实验5:修改obj_dir中任意一个文件(生成的源文件)

随便修改一个文件,前后对比,发现仍然是更新全部源文件。

结论

经过这么多的测试,你就应该明白了,对于verilator的--cc --exe阶段,也就是生成可执行文件之前的阶段,无论你是修改命令中给出的源文件(指Verilog源文件,c/cpp不算),还是修改生成之后的任意一个文件,都会导致下一次重新运行该命令的时候,全部重新编译和更新。

注意,修改生成的文件,是指的运行VTop.mk之前的那些文件,运行make之后生成内些文件不会跟着更新,它们的更新依靠的是make规则。

应用

好了,这个在文档没有找到,估计只能在源码中找了,先不管,反正测试结果就是这样!

我们看一下,这个特性能够让我们有什么应用呢?

  1. VTop.mk文件,生成VTop的规则,是依赖于obj_dir文件夹中源文件的,外部文件它是不管的!
  2. 如果你引入了外部生成的.o文件,这个文件不会被放在obj_dir文件夹中,只是在VTop.mk中提供外部.o文件的路径,以供链接使用
  3. 也就是说,如果你更新了外部的.o文件,按照生成规则来说,verilator的不知道这件事的,它会默认你的.o文件是一直不变的,这就意味着,你需要额外的规则来改变这件事
  4. 我们的放在工程,会在外部直接编译.c文件到.o文件,但是verilator不知道这件事,我们有两种方法
    1. 强制每次都重新编译Verilog和拷贝cpp源文件,这种方式就用了我们上面提到的那个特点,你只需要编译完成之后,再给VTop.mk随便编辑一下,下一次编译一定会全部更新的。但是这样似乎不太好……
      2.通过makefile来执行编译指令,并且识别.o文件是否更新,如果更新,则可以
      1. 强制编译和更新源文件,但是没有必要这么做,毕竟其他文件又没变
      2. 删除掉生成的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来指定位置和文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384581.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

帮助你成为高手的视频和资料

1. 为什么大多数人不会真正成功 博客链接 视频链接 2. TED演讲&#xff1a;真正拉开你与周围人之家差距的&#xff0c;是自学能力 视频链接 3 埃隆马斯克&#xff1a;第一性原理&#xff0c;少用类比&#xff0c;类比多了就不能抓住本质了 4 如何成为一个顶尖高手 文章链…

核心思想

程序员是能够改变世界的&#xff0c;至少是改变自己的世界。 对于重复的工作&#xff0c;你可以写一个shell脚本让他自动化执行&#xff1b; 对于麻烦的工作&#xff0c;你可以看看有没有相关的插件让它操作起来更简化&#xff0c;实在不行你自己造一个&#xff1b; 程序员必…

【数据结构】快速排序非递归算法及其改进

在学数据结构中排序这一章节的时候&#xff0c;有一道有关快速排序的作业题描述如下&#xff1a; 按下述要求编写快速排序的非递归算法&#xff1a; 定义一个栈&#xff08;或队列&#xff09;&#xff0c;把整个序列的上、下界入栈&#xff08;或队列&#xff09;。当栈&#…

【数据结构】对快速排序原理的理解(图解,通俗易懂)

学习数据结构时&#xff0c;书本上直接给出了快速排序的过程以及代码&#xff0c;对其原理解释的不够详细&#xff0c;琢磨代码后&#xff0c;发现其原理其实十分简单&#xff0c;简述如下&#xff1a; &#xff08;1&#xff09;在待排序列中找一个“中枢元素”&#xff08;书…

【离散数学】图论基础知识

文章目录1 图的基本概念2 图的连通性3 图的矩阵表示4 几种特殊的图4.1 二部图4.2 欧拉图4.3 哈密顿图4.4 平面图5 无向树6 生成树1 图的基本概念 无向图&#xff1a; 简而言之&#xff0c;边不带方向的图就是无向图。 有向图&#xff1a; 简而言之&#xff0c;边带方向的图就…

【操作系统】信号量解决经典同步问题

文章目录1. 基本结构2. P,V操作3. 信号量的应用3.1 信号量实现进程互斥3.2 信号量实现前驱关系4. 用信号量解经典同步问题4.1 生产者消费者问题4.2 读者写者问题4.3 狒狒过桥问题4.4 理发师理发问题4.5 哲学家进餐问题信号量机制是Dijkstra提出的一种卓有成效的进程同步工具。信…

【运筹与优化】单纯形法解线性规划问题(matlab实现)

文章目录单纯形法步骤&#xff1a;1.将线性规划问题化为标准形式2.列出单纯形表3.进行最优性检验4.从一个基可行解转换到另一个目标值更大的基可行解&#xff0c;列出新的单纯形表5.重复3、4直到计算结束为止举例单纯形法matlab实现单纯形法是一种解线性规划问题的算法&#xf…

【Linux系统编程学习】 GCC编译器

此为牛客网Linux C课程1.2&1.3的课程笔记。 0. 简介 1. gcc和g的安装 sudo apt install gcc g2. gcc常用参数选项 3. gcc工作流程 首先是预处理器对源代码进行预处理&#xff08;后缀名.i&#xff09;&#xff0c;主要做以下事情&#xff1a; 把头文件加入到源代码当中删…

Spring5底层原理之BeanFactory与ApplicationContext

目录 BeanFactory与ApplicationContext BeanFactory ApplicationContext 容器实现 BeanFactory实现 ApplicationContext实现 ClassPathXmlApplicationContext的实现 AnnotationConfigApplicationContext的实现 AnnotationConfigServletWebServerApplicationContext的实…

【Linux系统编程学习】 静态库的制作与使用

此为牛客网Linux C课程 1.4&1.5 的课程笔记。 0. 关于静态库与动态库 库就是封装好的、可服用的代码&#xff0c;而静态和动态是指链接。 这节课讲的是静态库&#xff0c;是指在链接阶段&#xff0c;会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中&…

【Linux系统编程学习】 动态库的制作与使用

此为牛客网Linux C课程1.6&1.7 的课程笔记。 1. 动态库命名规则 2. 动态库的制作 第一步&#xff0c;用gcc编译生成.o目标文件&#xff0c;注意要用-fpic参数生成与位置无关的代码&#xff1b; 第二步&#xff0c;用gcc的-shared参数生成动态库。 涉及到的两个参数之前学过…

【Linux系统编程学习】 静态库与动态库的对比与总结

此为牛客网Linux C课程 1.9 的课程笔记。 1. 前几节课知识总结 程序编译成为可执行文件的过程&#xff1a; 静态库制作过程&#xff1a; 动态库制作过程&#xff1a; 2. 静态库的优缺点&#xff1a; 3. 动态库的优缺点&#xff1a; 更多可参考&#xff1a;吴秦&#xff1…

【Linux系统编程学习】 Makefile简单入门

此为牛客网Linux C课程1.10&1.11&1.12 的课程笔记。 0. Makefile介绍 1. Makefile文件命名与规则 示例&#xff1a; 使用vim编写如下名为Makefile的文件&#xff1a; app:sub.o add.o mult.o div.o main.ogcc sub.o add.o mult.o div.o main.o -o appsub.o:sub.cgcc …

【Linux系统编程学习】 GDB调试器的简单使用

此为牛客网Linux C课程 1.13&1.14&1.15&1.16 的课程笔记。 0. GDB简介 1. 准备工作 想要使用gdb调试&#xff0c;首先需要用gcc的-g参数生成可执行文件&#xff0c;这样才能在可执行文件中加入源代码信息以便调试&#xff0c;但是注意这并不是将源文件嵌入到可执行…

【Linux系统编程学习】C库IO函数与系统IO函数的关系

此为黑马Linux课程笔记。 1. C标准IO函数工作流程 如图&#xff0c;以C库函数的fopen为例&#xff0c;其返回类型是FILE类型的指针&#xff0c;FILE类型包含很多内容&#xff0c;主要包含三个内容&#xff1a;文件描述符、文件读写指针的位置和I/O缓冲区的地址。 文件描述符&…

【Linux系统编程学习】 文件描述符

此为牛客网Linux C课程1.19课程笔记。 1. 文件描述符表 如图&#xff0c;我们知道每个进程都有其虚拟地址空间&#xff08;0~4G&#xff09;&#xff0c;其中3 ~ 4G部分为内核区。进程的进程控制块保存就在内核区&#xff0c;而PCB中维护一个打开文件描述符表&#xff0c;每个…

【Linux系统编程学习】Linux系统IO函数(open、read、write、lseek)

此为牛客网Linux C课程1.20课程笔记。 1.open函数 open函数有两种&#xff0c;分别是打开一个已经存在的文件和创建并打开一个不存在的文件。 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>// 打开一个已经存在的文件 int open(const…

【Linux系统编程学习】Linux进程控制原语(fork、exec函数族、wait)

此为牛客Linux C和黑马Linux系统编程课程笔记。 1. fork函数 1.1 fork创建单个子进程 #include<unistd.h> pid_t fork(void);作用&#xff1a;创建一个子进程。 pid_t类型表示进程ID&#xff0c;但为了表示-1&#xff0c;它是有符号整型。(0不是有效进程ID&#xff0…

【Linux系统编程学习】匿名管道pipe与有名管道fifo

此为牛客Linux C和黑马Linux系统编程课程笔记。 0. 关于进程通信 Linux环境下&#xff0c;进程地址空间相互独立&#xff0c;每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程和进程之间不能相互访问&#xff0c;要交换…

【Linux系统编程学习】信号、信号集以其相关函数

此为牛客Linux C和黑马Linux系统编程课程笔记。 文章目录0. 信号的概念1. Linux信号一览表2. 信号相关函数3. kill函数4. raise函数5. abort函数6. alarm函数7. setitimer函数8. signal函数9. 信号集10. 自定义信号集相关函数11. sigprocmask函数12. sigpending函数13. sigacti…