這是我寫的第一個測試
首先這個程式是TPO516的RX方向的一個component 我們管這個部分叫做FAS Regen. 它的作用就是給一個overhead被破壞掉的OTN frame重新插入正确的fas信号既f6f6f6282828,一共48bit.
這個程式一共有4部分組成,分别是:fas regen_env下的fasregen_checker和otu4_data_interface;在頂層中的otu_top_harness,以及top test case:FASRegenTest。
這個程式用了一個叫做two kingdom factory的trick 他的目的是利用OTU4DataInterface::type_id::set_type_override(FASRegenInterface::get_type());這句話來overide out4data_interface.即叫做custmize function。
第一步,借鑒别人的datainterface code:
/×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
`ifndef OTU4DataInterface_sv
`define OTU4DataInterface_sv
class OTU4DataInterface extends uvm_component;
`uvm_component_utils(OTU4DataInterface)
function new(string name = "", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual task sync();
endtask
virtual task read(output bit [319:0] data, output bit enable);
endtask
endclass
`endif //OTU4DataInterface_sv
//可以看到在這個code中,sync()和 read()function都是空的 友善以後override。
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××/
第二步 在圖—top— harness裡面寫入FasRegenInterface.這個程式是用來override datapathinterface的function。首先這個方程需要找到兩個來個ntc_otu_top_320的接口。一個為enable一個為inpute data。在top320中RX PATH,INSERT FAS BYTE中enable 信号為rx_lite_frm_oof_fas_en,data為fas regen data. 将這兩個信号賦給harness中的readfunction的 data和enable,這樣就完成了data的進入dut的這個過程。這個語句always @(posedge sys_clk) fas_regen_enable <= dut.rx_lite_frm_oof_fas_en;使fas—en比regen—enable早一拍。
/×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
logic fas_regen_enable;
always @(posedge sys_clk) fas_regen_enable <= dut.rx_lite_frm_oof_fas_en;
class FASRegenInterface extends OTU4DataInterface;
`uvm_component_utils(FASRegenInterface)
function new(string name = "", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual task sync();
@(posedge sys_clk);
endtask
virtual task read(output bit[319:0] data, output bit enable);
data = dut.rx_fas_regen_data;
enable = fas_regen_enable;
endtask
endclass
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
***************************************************************************************************************************/
下一個module是fas policy。他的作用是把6個fas bytes打亂,然後進入dut。
constraint solve_order {solve bad_fas before mask;}
constraint frame_size {random_frames > 0; random_frames < 2000;}
constraint fas_dist {bad_fas dist {0:=good_fas_dist, 1:=bad_fas_dist};}//指定bad fas為1。good為2 weighted distribution,非配資料.
constraint mask_value {(bad_fas) -> mask != 48'h0; (!bad_fas) -> mask == 48'h0;} //bad fas = 1. mask dont equal to 0 and do xor with fas byte.-> is implication constrain, it is equal !A//B. 這句話中表示若左面真的是 badfas,則右面mask一定能夠不為0. 若左面為goodfas 則右面mask一定為0
function new(string name);
super.new(name);
setRandomizeControl(ON_TRANSACTION); //on transaction means random function will active when execute function begin.
endfunction
function void post_randomize();
if(!frame_count_flag) begin
this.max_lifecycle = random_frames;
end
endfunction
function void setFrameCount(int frame_count);
frame_count_flag = 1'b1;
setMaxLifecycle(frame_count);
endfunction
function void setRandomizeDist (int good_fas_dist, int bad_fas_dist);
this.good_fas_dist = good_fas_dist;
this.bad_fas_dist = bad_fas_dist; // 把這個class裡面的bad_fas_dist給了setrandomizeddist中的bad—fas-dist。這個變量不再這個檔案中
endfunction
function void execute(OTNFrame txn, ExecutionContext cntxt);
if(!this.randomize()) `uvm_fatal("RANDOMIZATION_ERROR", "Failed to randomize FASPolicy")// 有random都需要這個語句來開始執行random function.
`uvm_info("FASPolicy", $sformatf("bad_fas = %0d, mask = %0h", bad_fas, mask), UVM_MEDIUM)
txn.getAlignment().setFAS(48'hf6f6f6282828 ^ mask); //因為mask是一個random,當mask為1 就開始破壞fas。
endfunction
endclass
`endif //FASPolicy_sv
******************************************************************************************************************************************
******************************************************************************************************************************************/
下一部分是checker, 他負責檢查從dut出來的資料, 看看是否是正确的fasbyte.
下一個就是頂層的testcase,這個需要在questa 裡面運作