Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(三)
在前面一篇文章中分享了作者如何使用 verilator 以及 C++ 來模擬一個用 SystemVerilog 模組,在這篇文章中,將會分享另外一種方法,也就是用 verilator 以及 SystemC 來達成同樣的事情。
SystemC
SystemC 說到底還是 C++ 的 library,那麼額外引入 C++ 這個額外的 library 能得到什麼好處呢?作者認為有以下兩個好處:
- 現今 SystemC 很常拿來作硬體的 approximate timing model 或是 cycle accurate model,有可能可以直接利用這些 model 的程式碼來作驗證。
- SystemC 內建了模擬平行化的功能如
SC_THREAD
,這在硬體測試中對應到 Verilog 如initial
的功能,這點讓 SystemC 跟純 C++ 相比,更適合拿來驗證 Verilog。
Hello Verilator (SystemC version)
上一篇中,用 verilator 以及 C++ 驗證的步驟如下:
- 撰寫 testbench
testbench.cpp
。 - 準備可合成之待測模組
design_under_test.v
。 - 把待測試模組轉換成 C++(或是 SystemC),並指名要使用的 testbench
verilator design_under_test.v --exe testbench.cpp --cc
。 - Verilator 產生的檔案都在
obj_dir
資料夾(這個是預設名稱)。 - 在該資料夾下面編譯產生 binary
make -C obj_dir -f Vdesign_under_test.mk
。 - 執行模擬
./obj_dir/Vdesign_under_test
。
用 SystemC 的話,步驟其實是一樣的,除了第三個步驟會的指令有一點不同:
verilator design_under_test.v --exe testbench.cpp --sc
唯一的不同就只是把 --cc
替換成 --sc
。另外,有些系統安裝的 verilator 版本沒設定正確,例如在 ArchLinux 下,可能需要另外透過環境變數指定 SystemC 的安裝位置:
SYSTEMC=/usr verilator design_under_test.v --exe testbench.cpp --sc
SystemC testbench
實做 sc_main
我們暫時先拿一個空的 testbench.cpp
來跑整個流程。
1#include "Vdesign_under_test.h"
2#include <memory>
3#include <iostream>
4#include <systemc>
5int sc_main(int, char**)
6{
7 std::unique_ptr<Vdesign_under_test> dut(new Vdesign_under_test("dut"));
8 sc_start(100.0, SC_NS);
9 return 0;
10}
sc_main
什麼都沒有接。
為此,我們創造 Testbench
這個 class 來幫 design_under_test
接上必要的 sc_signal
:
1using namespace sc_core;
2SC_MODULE(Testbench) {
3 sc_clock clk;
4 sc_signal<bool> rst;
5 sc_signal<bool> valid;
6 sc_signal<unsigned> data;
7public:
8 SC_HAS_PROCESS(Testbench);
9 Testbench(
10 const sc_module_name &name,
11 Vdesign_under_test *dut
12 ): sc_module(name) {
13 dut->clk(clk);
14 dut->rst(rst);
15 dut->valid(valid);
16 dut->data(data);
17 }
18};
sc_main
裡面宣告 Testbench
:
1int sc_main(int, char**)
2{
3 std::unique_ptr<Vdesign_under_test> dut(new Vdesign_under_test("dut"));
4 std::unique_ptr<Testbench> testbench(new Testbench("testbench", dut.get()));
5 sc_start(100.0, SC_NS);
6 return 0;
7}
實做 SC_THREAD
最後一個步驟中,我們加入了兩個 SC_THREAD
,一個是負責驅動 rst
的 Reset()
,另外一個是負責監視輸出資料的 Monitor()
:
1Testbench(
2 const sc_module_name &name,
3 Vdesign_under_test *dut
4): sc_module(name), clk("clk", 1.0, SC_NS) {
5 dut->clk(clk);
6 dut->rst(rst);
7 dut->valid(valid);
8 dut->data(data);
9 SC_THREAD(Reset);
10 SC_THREAD(Monitor);
11}
rst
的 Reset()
如下:
1void Reset() {
2 rst.write(true); // initial begin rst = 1;
3 wait(5.0, SC_NS); // #5
4 rst.write(false); // rst = 1
5 wait(5.0, SC_NS); // #5
6 rst.write(true); // rst = 0 end
7}
valid
是 1 則把 data
印出來,其函數實做如下:
1void Monitor() {
2 wait(rst.negedge_event()); // @(negedge rst)
3 wait(rst.posedge_event()); // @(posedge rst)
4 while (true) { // forever begin
5 wait(clk.posedge_event()); // @(posedge clk)
6 if (valid.read())
7 std::cout << char(data.read()) << std::endl;
8 } // end
9}
重新跑一次步驟 5-6 之輸出如下,也就是我們預期的結果:
1 SystemC 2.3.3-Accellera --- Jan 16 2020 17:56:30
2 Copyright (c) 1996-2018 by all Contributors,
3 ALL RIGHTS RESERVED
4H
5e
6l
7l
8o
可以看到在 SystemC 的版本中,「負責驅動 rst
」跟「監視輸出資料」兩個獨立功能是放在兩個獨立函數內。因此相比純 C++ 的版本,SystemC 的版本有更好的擴展性。
系列文連結
-
Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(一)
-
Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(二)
-
Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(三)
- Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(一)
- Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(二)
- Hello Verilator—高品質&開源的 SystemVerilog(Verilog) 模擬器介紹&教學(三)