包的定義
- 在大型的驗證項目中,很容易出現模塊重名的情況。
- 對于重名的硬件模塊我們可以將它們置入到不同編譯的庫中。
- 對于重名的軟件類、方法等,我們可以將它們置入到不同的包中。
- 我們可能使用不同的驗證IP,我們也無法預測這些類名是否可能重名。
- 通過包(package)可以將關聯的類和方法并入到同一個邏輯集合中。
- 為了使得可以在多個模塊(硬件)或者類(軟件)之間共享用戶定義的類型,SV添加了包(package)。
- 用戶自定義的類型譬如類、方法、變量、結構體、枚舉類等都可以在package...endpackage中定義.
package definitions;
parameter VERSION = "1.1";
typedef enum{ADD,SUB,MUL} opcodes_t;
typedef struct {
logic [31:0] a,b;
opcodes_t opcode;
} instruction_t;
function automatic [31:0] multiplier (input [31:0] a, b);
return a * b;
endfunction
endpackage
- module、interface、class等可以使用包中定義或者聲明的內容。
- 可以通過域的索引符號
::
直接引用。
definitions::parameter
definitions::instruction_t inst
- 可以指定索引一些需要的包中定義的類型到指定的域中。
module M
import definitions:: instruction_t;
instruction_t inst;
endmodule
- 通過通配符*來將包中所有的類別導入到指定的域中。
module M
import definitions :: *
instruction_t inst;
endmodule
- 可以通過域的索引符號
::
直接引用。
module ALU(input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result);
always_ff @(posedge clock) begin
case (IW.opcode)
definitions::ADD:result = IW.a + IW.b;
definitions::SUB : result = IW.a - IW.b;
definitions::MUL :result =
definitions::multiplier(IW.a, IW.b);
endcase
end
endmodule
一般使用這種直接引用類型比較繁瑣,是為了特意強調某些類型、變量是來自某個包,避免了重名以及方便代碼閱讀。
- 可以指定索引一些需要的包中定義的類型到指定的域中。
module ALU(...);
import definitions::ADD;
import definitions::SUB;
import definitions::MUL;
import definitions::multiplier;
always_comb begin
case(IW.opcode)
ADD :result = IW.a + IW.b;
SUB:: result = IW.a - IW.b;
MUL : result = multiplier(IW.a, IW.b);
endcase
end
endmodule
例如,在ALU模塊中先導出了枚舉值ADD,SUB,MUL和函數multiplier.
因此就可以在always語句塊中就可以直接使用這些類型了。
如果覺得從包中逐一導出比較繁瑣:[也可以采用下面的方法]
image.png
示例問題:
image.png
- 然而這兩個package 中同名的類,它們的內容是不相同的,實現的也是不同的功能。
- 由于我們將這些重名的類歸屬到不同的package中編譯,這樣如果要使用不同package中的的同名類,他們只需要注明要使用哪一個package中的。
module mcdf_tb;
chnl_pkg:: monitor mon1 = new();
arb_pkg:: monitor mon2 = new();
endmodule
由于類名本身有沖突,這使得在引用類的時候,不得不使用直接索引的方式,這在兩個包中導出多個類型時就不方便了。在實際代碼中一般建議包中的類型名稱帶有包名的前綴
因此可以通過通配符索引類型的方式來導入到模塊中
image.png
- 從上述的簡單例子來看,package這個容器可以對類型做一個隔離的作用
- package的意義在于將軟件(類、類型、方法等)封裝在不同的域中,以此來與全局的域進行隔離。
包與庫的區分
- 庫是編譯的產物,硬件(module 、interface、program)都會編譯到庫中,如果不指定編譯庫的話,會被編譯進入默認的庫中。
- 庫可以容納硬件類型,也可以容納軟件類型,例如類、方法和包
- 包只能容納軟件類型例如類、方法和參數