这是我写的第一个测试
首先这个程序是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。
/**********************************************************************************************************************************
************************************************************************************************************************************
`ifndef FASPolicy_sv
`define FASPolicy_sv
class FASPolicy extends OTNPolicyBase;
local rand int random_frames;
local bit frame_count_flag = 1'b0;
local rand bit [47:0] mask;
local rand bit bad_fas;
local int good_fas_dist = 1; //deault value
local int bad_fas_dist = 1;
/**
* @literal constraints dictating the orders in which random variables are solved
*/
constraint solve_order {solve bad_fas before mask;}
/**
* @literal constraint - frame_size: Ensures that the number of frames is between 0 and 2000
*/
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
/**
*
*
* @param name -
*/
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
/**
* The number of frames for which the Policy will execute
*
* @param frame_count
*/
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
/**
*Execute is called once per frame. Physically inserts FAS bytes into the frame.
*
* @param txn -
* @param cntxt -
*/
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.
/****************************************************************************************************************************************************
******************************************************************************************************************************************************
`ifndef FASRegenChecker_sv
`define FASRegenChecker_sv
class FASRegenChecker extends uvm_component;
`uvm_component_utils(FASRegenChecker)
local OTU4DataInterface datapath;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
datapath = OTU4DataInterface::type_id::create("datapath", this);
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
bit [319:0] data; //一clock cycle有320byte
bit enable;
datapath.sync();
datapath.read(data, enable);
if(enable) begin
if(data[319:272] == 48'hf6f6f6282828) begin 进行比较 判断
`uvm_info("CHECKER", "FAS found - Simulation of the current frame is passing!", UVM_MEDIUM)
end
else begin
`uvm_error("CHECKER", "FAS not correct - Simulation of the current frame fails!")
end
end
end
endtask
endclass
`endif //FASRegenChecker_sv
*********************************************************************************************************************************************************
**********************************************************************************************************************************************************/
下一个就是顶层的testcase,这个需要在questa 里面运行
/**************************************************************************************************************************************************
****************************************************************************************************************************************************
`ifndef FASRegenTest_sv
`define FASRegenTest_sv
class FASRegenTest extends BaseTest; //因为我没有env这个class所以我需要extends BaseTest 这里包含了环境配置
`uvm_component_utils(FASRegenTest)
protected FASRegenChecker check;
protected ProcessStack stack; //policy need stack to run
protected FASPolicy good_fas; //例化policy
protected FASPolicy fas_corrupt;
protected Node node; //在mld模块右侧
function new(string name = "", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase); // 不是 super。phase
check = FASRegenChecker::type_id::create("check", this); //声明的变量都需要在这里contruct
good_fas = new("good_fas");
fas_corrupt = new("fas_corrupt");
endfunction
virtual function void connect_phase(uvm_phase phase);
Node nodes [$];
MasterGraph graph = Framework::getInstance().getMasterGraph();
graph.getTransceiverNodes("mld_xcvr", nodes);
node = nodes[0];
stack = ProcessStack::construct("OTNFrame", node, "mld_xcvr", ProcessStack::SRC);
good_fas.setRandomizeDist(1, 0); //全是 goodfas
good_fas.setFrameCount(250); // goodfas运行250frame
fas_corrupt.setRandomizeDist(2, 5); //badfas domains 2/7,goodfas 5/7
fas_corrupt.setFrameCount(1000); //对1000frame 进行corrupt
stack.add(good_fas).next().add(fas_corrupt).finish();
endfunction
virtual task main_phase(uvm_phase phase);
phase.raise_objection(this);
stack.start(phase, 1'b0);
phase.drop_objection(this);
endtask
endclass
`endif //FASRegenTest_sv
**************************************************************************************************************************************************
**************************************************************************************************************************************************/