細數Quartus系列綜合器對SystemVerilog支持上的5個槽點

Quartus II以及後來的Quartus Prime(截止本文寫作時其最新版本是v16.1)是Altera公司爲自家FPGA編寫的集成開發環境,包括編譯、綜合工具。工具不錯,但對SystemVerilog的支持實在槽點多多,下面僅列出本人遇到的5個無力吐槽的編譯器大BUG:

1.不支持在interface中聲明interface的實例

示例代碼:


interface test_if #(
   parameter BITW = 16
);
   logic [BITW-1:0] sigs;
endinterface

interface nest_if #(
   parameter BITW = 16
);
   test_if #(.BITW(BITW)) tifi();
endinterface

module multiinstif #(
   parameter BITW = 8
) ;
   nest_if #(.BITW(BITW)) nifi();
endmodule

現象:quartus_map.exe直接崩潰,屢試不爽!
受影響的版本:Quartus Prime v16.0、v16.1,舊版Quartus還未測試,也懶得測試了-_-!
官方給出的解決方案:工程目錄下新建一個quartus.ini文件,在其中加入一行:sgn_use_new_verific = on
解決方案可行性:可以編譯通過,但貌似該模式仍然是未完善的狀態,某些語言特性無法得到支持,例如——多維數組信號
評價:看你運氣了,大工程的話效果會怎麼樣實在不敢想象。

2.對interface中的條件generate代碼支持不好

示例代碼:

interface test_gen_if #(
   parameter int BITW = 16
);
   generate
       if (BITW > 0) begin: SIGS
           logic[BITW-1:0] sigs;
       end: SIGS
   endgenerate
endinterface

module multiinstif(
   input clk,
   input rst
);
   test_gen_if #(.BITW(0)) tgifi_01();
   test_gen_if #(.BITW(0)) tgifi_02();
   test_gen_if #(.BITW(0)) tgifi_03();
   test_gen_if #(.BITW(0)) tgifi_04();
   test_gen_if #(.BITW(0)) tgifi_05();
endmodule

現象:當multiinstif中聲明的test_gen_if實例的例化參數BITW賦值0,且聲明超過4個實例時,quartus_map.exe直接崩潰,屢試不爽!
受影響的版本:QuartusPrime v16.0,v16.1版貌似已經解決了,舊版的QuartusII沒測試過,同樣,懶得測了-_-!
官方解決方案:還是用quartus.ini文件加入一行:sgn_use_new_verific = on 的辦法
評價:同上

3.某些情況下不能正確識別和區分常量和變量

示例代碼:

interface test_if #(
   parameter BITW = 16
);
   logic [BITW-1:0] sigs;
endinterface

package test_pkg;
   function automatic int test_calc(int bitw);
       return bitw + 1;
   endfunction
endpackage

module test_mod #(
   parameter BITW = 8
) ( input bit clk, input wire rst);
   test_if #(.BITW(BITW)) tifi();
   localparam int bitw_ofcalc = test_pkg::test_calc($size(tifi.sigs,1));    // on this line Quartus reports error message: can't pass value from actual to argument bitw
   initial $warning("DEBUG: bitw_ofcalc = %0d", bitw_ofcalc);
endmodule

現象:Quartus編譯報告 “ can’t pass value from actual to argument bitw”,就像代碼中註釋的說明一樣
受影響的版本:Quartus Prime v16.0、v16.1,同樣的,舊版懶得測試了-_-!
官方解決方案:將代碼中的 test_if #(.BITW(BITW)) tifi(); 改爲 test_if #(.BITW(8)) tifi();
評價:無力吐槽——傳遞 BITW 的目的就是爲了提高代碼的可重用性,這樣來整,對每一個不同值的BITW我都得寫一個與test_mod代碼相同但名稱不同的模塊,這是要累死我的節奏嗎?

4.對分層標識符支持不好

示例代碼:

interface test_if #(
   parameter int test_bitw = 1
);
    generate
        if (test_bitw > 0) begin: SIGS
            logic[test_bitw-1:0] sig;
        end
    endgenerate
endinterface

module test_mod(
   test_if tifi,
    output wire sig_o
);
    generate
        if (tifi.test_bitw > 0) begin: OSIG // quartus complains : constant expression cannot contain a hierarchical identifier
            assign sig_o = |tifi.SIGS.sig;
        end
    endgenerate
endmodule

現象:quartus在有註釋的那一行報告”constant expression cannot contain a hierarchical identifier“
受影響的版本:Quartus II v13.1、Quartus Prime v16.0、v16.1,其他版本懶得測了,咱又不在Altera領工資-_-!
官方解決方案:等下一版Quartus Prime修復……
評價:又一次無力吐槽——SystemVerilog標準(IEEE std. 1800)中並未規定不能引用分層標識符,就算你聲明自己實現的只是該標準的一個子集,那爲什麼按下面的代碼寫test_mod時又能編譯了?

module test_mod(
   test_if tifi,
    output wire sig_o
);
    localparam bit osig_en = tifi.test_bitw > 0 ? 1'b1 : 1'b0;
    generate
        if (osig_en) begin: OSIG    // quartus passed the compilation with no error message
            assign sig_o = |tifi.SIGS.sig;
        end
    endgenerate
endmodule

好吧,我等……再說幾句:上面的解決方案只適用於Quartus Prime v16.0、v16.1,在Quartus II v13.1上仍然繞不過去,而一些舊的芯片例如Cyclone III,則因爲新版的Quartus Prime不支持,加上Altera官方並不願意爲舊版的QuartusII開發補丁,因此這樣的問題便變得無解了,悲劇吧?

5.SystemVerilog代碼的編譯錯誤定位不準確

我就不放示例代碼了,因爲要重現這個問題太麻煩,不是簡單的幾行代碼就能搞出來的。現象就是:Quartus編譯器給出的錯誤信息不能完全反映代碼的錯誤位置,有時甚至奇葩到對一行很明顯沒問題的語句報錯,爲了正確定位編譯錯誤我不得不採用費時費力的排除法,嚴重降低了開發效率。
根據這些現象個人懷疑目前版本的Quartus編譯器程序中存在着內存管理漏洞,導致在解析某些錯誤代碼時觸發內存訪問越界或內存泄漏的問題,並最終造成這樣莫名其妙的報錯,由此看來,Quartus編譯器的軟件質量實在堪憂啊。
個人的解決辦法:就像上面說的一樣,採用排除法來定位編譯錯誤,具體點就是——先不停的註釋代碼,直到編譯器不再報錯,然後在這樣的代碼版本基礎上一塊一塊的增加不同位置的代碼,看哪一塊代碼增加後會導致編譯器報錯。這真的是體力活兒啊!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章