以下文章來源于AdriftCoreFPGA芯研社,作者CNL中子
對于許多FPGA/IC工程師而言,設計實現(xiàn)游刃有余,驗證仿真卻常成短板——傳統(tǒng)驗證方法面臨兩難困局:學習UVM需投入大量時間成本,而純Verilog自仿又會陷入重復造輪子的低效循環(huán)。以通信協(xié)議仿真為例,僅報文解析就需要重寫整套解析邏輯,相當于用Verilog再實現(xiàn)一次協(xié)議棧,耗時費力。
此時,Python的生態(tài)優(yōu)勢便鋒芒盡顯。其豐富的字符串處理庫可直接解析報文,配合Cocotb框架,僅需少量Python代碼即可構(gòu)建高效測試平臺,將驗證工作量壓縮70%以上。Cocotb的獨特價值正在于此:用Python解放驗證生產(chǎn)力,讓工程師專注于設計創(chuàng)新而非重復勞動。
? 前言
? cocotb+pytest
? 開源cocotb仿真環(huán)境介紹
前言
在日常開發(fā)中,我們的仿真一般是串行執(zhí)行的。如果想批量做回歸測試,就會明顯感受到速度之慢:當我們焦急等待仿真結(jié)果時,CPU 卻在“摸魚”,只有一個核心在跑,其余核心幾乎閑置。這時難免會想——我花了幾千塊錢搭的配置,不是讓CPU在這里摸魚的
那能不能把 CPU 的每一個核心都壓榨起來呢?
答案是肯定的。借助cocotb + pytest,我們可以輕松實現(xiàn)多核并行仿真,最大化利用 CPU 資源。
如下圖所示,圖一為普通串行仿真,共 9 個 case,耗時 358.90 s;而使用 6 核并行仿真,僅用 117.03 s,速度提升足足3 倍。乍看只是節(jié)省了 4 分鐘,但這還只是一個簡單的測試用例集。若你的用例規(guī)模很大,多核可能只需 1 小時,而單核卻要 3 小時甚至更久,可見效率差距巨大。
下面我將介紹如何充分壓榨 CPU 的性能,并順帶介紹一下本公眾號開源的AFX-Cocotb-Pytest庫,讓你無需繁瑣配置即可開箱即用,實現(xiàn)真正意義上的高效并行仿真。


介紹
pytest-xdist
pytest-xdist是 pytest 的增強插件,通過并行執(zhí)行測試用例與分布式運行測試來顯著加速整個測試流程。
借助多進程并行、任務負載均衡以及跨機器分布式執(zhí)行,它能夠最大化利用 CPU 資源,特別適用于包含大量測試的大型工程。
如果希望在仿真環(huán)境中充分壓榨多核性能,就需要在我們的 cocotb 測試框架中引入并配置pytest-xdist,以實現(xiàn)高效的并行仿真執(zhí)行。
?
安裝插件
pip install pytest-xdist
?
并行運行所有測試
pytest -n auto
-n auto會自動根據(jù) CPU 核心數(shù)分配 worker 數(shù)量。
你也可以手動指定 worker 數(shù):
pytest -n 8
?
cocotb+pytest
pytest
在 cocotb 進階專欄的《用 Python 給 Verilog 設計自仿進階(二):實現(xiàn)仿真平臺 Linux/Win 多平臺兼容》以及《用 Python 給 Verilog 設計自仿進階(三):FPGA 仿真,如何兼容 VCS、Iverilog、Modelsim 等多平臺仿真器》中,我們已經(jīng)借助 pytest 實現(xiàn)了跨系統(tǒng)、跨仿真器的批量自動化仿真。
然而,這些批量仿真仍未真正發(fā)揮出多核 CPU 的計算潛力。接下來,我將介紹如何將pytest-xdist融入現(xiàn)有 pytest 測試體系,從而實現(xiàn)更高效的并行仿真加速。
pytest-xdist
要實現(xiàn)多核并行仿真,關鍵在于正確管理仿真過程中使用的文件資源。在單核環(huán)境下,所有測試用例共用同一套文件進行仿真,彼此之間不存在競爭關系,因此不會發(fā)生讀寫沖突。然而,當啟用多核并行時,多個 worker 可能會同時對同一文件進行增刪查改,從而導致仿真過程出現(xiàn)競爭條件,最終引發(fā)報告錯誤。
對于 Verilog 仿真而言,最核心的文件包括filelist和sim_build,其中sim_build是仿真的實際工作目錄。因此,為了保證并行仿真的獨立性,我們需要根據(jù) worker 的 ID(即每個 CPU 核心對應的 worker 進程)為它們分別創(chuàng)建并訪問獨立的 filelist 和 sim_build,從而避免任何文件級沖突。
首先獲取當前worker進程的id
worker_id = os.getenv("PYTEST_XDIST_WORKER","gw0")
filelist
基于 worker ID 創(chuàng)建獨立的 filelist 時,這里的 filelist 是通過指定 RTL 根目錄,由 Python 自動遍歷所有.v與.sv文件生成的。隨后,我們根據(jù)生成的 filelist 獲取文件路徑,并將其傳遞給cocotb_run的verilog_sources。
這樣做的好處在于:
1.無需手寫 filelist
只需將 RTL 文件放入指定目錄,即可自動收集所有 Verilog/SV 模塊,降低維護成本。
2.生成的 filelist 可直接供波形工具使用
例如 VCS、ModelSim、Verdi 等工具可以利用 filelist 實現(xiàn)源碼追蹤(trace),無需重復配置路徑。
3.并行仿真時便于為每個 worker 創(chuàng)建獨立 filelist
避免文件競爭問題。
如果你的項目不是通過 filelist 動態(tài)生成verilog_sources,而是手動指定 RTL 文件列表,那么你可以忽略這一機制。
filelist_path = Path(filelist+worker_id+".f").resolve()
sim_build
在并行仿真中,每個 worker 需要使用獨立的仿真工作目錄(sim_build),以避免多個進程同時讀寫同一目錄而導致文件沖突?;?worker ID 創(chuàng)建獨立的sim_build可以這樣實現(xiàn):
sim_build = os.path.join(sim_path,"sim_build",f"{safe_test_name(request.node.name)}_{worker_id}")
隨后,將生成的sim_build傳遞給cocotb_run即可讓每個 worker 使用獨立的仿真空間:
cocotb_test.simulator.run( python_search=[str(tb_files)], verilog_sources=verilog_sources, toplevel=toplevel, module=module, compile_args=compile_args, sim_args=sim_args, parameters=parameters, sim_build=sim_build, extra_env=extra_env, waves=waves )
這樣即可確保每個并行任務都在自己的仿真目錄中獨立運行,避免競爭條件,提高并行執(zhí)行的穩(wěn)定性。
?
開源cocotb仿真環(huán)境介紹
當然,如果你覺得上述配置流程較為繁瑣,也可以直接使用我提供的afx_cocotb_test_run庫。該庫的目標是簡化 pytest + cocotb 仿真環(huán)境的代碼編寫與配置復雜度。
只需將該文件放在你的 Python 仿真腳本所在目錄,并直接調(diào)用即可完成仿真運行。
目前該庫已支持VCS和Icarus等主流仿真器。如果你需要支持其他仿真器,也可以參考我提供的 VCS 與 Icarus 示例進行擴展,非常方便。
fromafx_cocotb_test_runimport*
在自己的Python代碼末尾加上類似下面代碼的模板即可
################################################################### RUN TEST ################################################################### importos importpytest @pytest.mark.parametrize("cycle", [10,30,40,80]) @pytest.mark.parametrize("a", [3,5]) deftest_run(request,cycle,a): simulator = os.environ.get("SIM","") waves = os.environ.get("WAVES","") parameters = {k.upper(): vfork, vinrequest.node.callspec.params.items()} afx_test_run(request,ctb="cocotb_top",tc="tb_top",wave=waves,sim=simulator,parameters=parameters)
?
在使用afx_cocotb_test_run進行仿真時,我們可以通過afx_test_run提供的多種參數(shù)靈活配置整個運行環(huán)境。
這些參數(shù)覆蓋了仿真器選擇、波形開關、測試平臺路徑、RTL 文件路徑以及可選的參數(shù)傳遞等內(nèi)容,使得 cocotb + pytest 的仿真流程高度可控、易擴展。
以下是afx_test_run支持的主要配置項:
sim:str="vcs", # 指定使用的仿真器,如 "vcs" 或 "icarus"
wave:str="1", # 波形開關,1 表示生成波形,0 表示關閉
ctb:str="cocotb_top", # cocotb Python 頂層模塊名
tc:str="tb_top", # Verilog/SystemVerilog 頂層 testbench 模塊名
filelist:str='../sim/filelist', # 自動生成或指定的 filelist 路徑
tests_dir:str='../sim/', # 工作空間路徑
include_list:str='../../design/incl', # include 頭文件目錄
tb_list:str='../../verify/tb', # Verilog/SV/Python testbench文件路徑
pkg:str='../../design/pkg', # package 所在目錄
rtl:str='../../design/rtl', # RTL 源碼目錄
sim_ip:str='../ip', # 仿真依賴的 IP 文件目錄
parameters:dict[str,int] = {} # Verilog/SystemVerilog 頂層的可配置參數(shù)
這些參數(shù)的設計使得用戶可以根據(jù)自己的工程結(jié)構(gòu)輕松適配,無需修改大量路徑或腳本,即可快速構(gòu)建 cocotb 的跨平臺仿真環(huán)境,同時讓pytest-xdist并行加速的配置更自然、易于集成。
以上述模板為例,我們將仿真器類型和是否生成波形配置為環(huán)境變量,在使用 pytest 時可以靈活指定。
WAVE=1SIM=vcs pytest cocotb_top.py
測試用例參數(shù)
同時,我們可以傳入 RTL 頂層參數(shù)(如parameter A)以及測試環(huán)境參數(shù)(如表示仿真時鐘頻率的cycle)。
對于測試環(huán)境參數(shù),需要特別注意:cycle并不是直接傳入 RTL,而是作為測試用例的參數(shù),用于控制仿真時的行為,例如仿真時鐘頻率、數(shù)據(jù)流中反壓的概率,或者其他與特定測試場景相關的設置。
例如,如果我們在測試用例中使用:
# @pytest.mark.parametrize("a", [3,5])
@pytest.mark.parametrize("cycle", [10,20])
@pytest.mark.parametrize("press", [0.3,0.8])
deftest_run(request,cycle,press):
parameters = {k.upper(): vfork, vinrequest.node.callspec.params.items()}
afx_test_run(request,ctb="cocotb_top",tc="tb_top",wave=waves,sim=simulator,parameters=parameters)
則會生成 4 個不同的測試 case:
1. 時鐘頻率 10,反壓概率 0.8
2. 時鐘頻率 10,反壓概率 0.3
3. 時鐘頻率 20,反壓概率 0.8
4. 時鐘頻率 20,反壓概率 0.3
在 Python 腳本中,需要配合從環(huán)境變量獲取參數(shù),例如:
@cocotb.test()
asyncdefdff_simple_test(dut):
cycle =int(os.getenv("PARAM_CYCLE","20"))
press =float(os.getenv("PARAM_PRESS","0.3"))
# clock
awaitcocotb.start(generate_clock(dut,cycle,"ns",0))
這樣就可以保證測試用例能夠根據(jù)不同參數(shù)自動生成,并與仿真環(huán)境動態(tài)關聯(lián)。
波形查看
在Python仿真文件夾下輸入命令即可仿真:
WAVES=1pytest cocotb_top.py -v -s -n auto
在sim_build產(chǎn)生四個仿真結(jié)果
AdriftCore@AdriftCore:/sim_build$ls test_run_0_3_10_gw0 test_run_0_3_20_gw1 test_run_0_8_10_gw2 test_run_0_8_20_gw3
每個仿真結(jié)果都會有其對應的波形
AdriftCore@AdriftCore:/sim_build/test_run_0_3_10_gw0$ls cocotb_top cocotb_top.daidir cocotb_top_ucli.do com.log Makefile novas_dump.log pli.tab simulate.log tb_top.fsdb ucli.key um8pni2k_results.xml vcs_lib
?
鏈接
AFX-CocotbSIMENV的功能不僅限于 pytest 的并行仿真,這只是其中的一部分。由于篇幅所限,這里無法一一展開說明。后續(xù)版本中,AFX-CocotbSIMENV 會將實際仿真中常用的功能封裝為函數(shù)或方法集成到庫中,從而減少重復操作,提高仿真效率。
https://github.com/AdriftXCore/CocotbSIMENV https://github.com/AdriftXCore/CocotbSIMENV/blob/master/verify/tb/afx_cocotb_test_run.py
-
FPGA
+關注
關注
1660文章
22406瀏覽量
636047 -
cpu
+關注
關注
68文章
11274瀏覽量
224906 -
仿真
+關注
關注
54文章
4479瀏覽量
138207 -
Verilog
+關注
關注
30文章
1373瀏覽量
114511
原文標題:用Python給Verilog設計自仿進階:FPGA仿真如何極致壓榨CPU
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術(shù)江湖】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
大數(shù)據(jù)時代:CPU+FPGA將大有可為
FPGA真的能取代CPU和GPU嗎?
數(shù)字預失真如何改善數(shù)字信號發(fā)生器的失真性能?
介紹一下波形仿真如何進行
一種利用FPGA的CPU設計
FPGA為什么比CPU和GPU快
FPGA和CPU如何搭配?
基于FPGA的仿真如何工作
FPGA仿真如何極致壓榨CPU性能
評論