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.pswp.cn/news/384581.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384581.shtml
英文地址,請注明出處:http://en.pswp.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…