MCDT测试结构
如何实现
- 产生数据transaction激励的组件channel generator
- 将这些数据解析并且驱动到 channel interface上的驱动组件channel initiator
channel simulator
class chnl_trans ;
rand bit[31:0] data[] ;
rand int ch_id ;
rand int pkt_id;
rand int data_nidles ;
rand int pkt_nidles;
bit rsp;
local static int obj_id = 0;
constraint cstr{
soft data.size inside {[4:8]} ;
foreach(data[i]
data[i] == 'hco0o_o000 + (this.ch_id<<24) + (this.pkt_id<<8)+ i ;
soft ch_id == 0;
soft pkt_id == 0;
data_nidles inside {[0:2]} ;
pkt_nidles inside {[1:10]};
};
function new() ;
this.obj_id++;
endfunction
function chnl_trans clone () ;
chnl_trans c = new () ;
c.data = this.data;
c.ch_id = this.ch_id;
c. pkt_id = this.pkt_id;
c.data_nidles = this.data_nidles;
c.pkt_nidles = this.pkt_nidles;
c.rsp = this.rsp;
return c;
endfunction
endclass: chnl_trans
class chnl_initiator;
local string name;
local virtual chnl_intf intf;
mailbox #(chnl_trans) req_mb;
mailbox #(chnl_trans) rsp_mb;
function new(string name = "chnl_initiator");
this.name = name;
endfunction
function void set_interface(virtual chnl_intf intf);
if(intf ==null)
$error (" interface handle is NULL,
please check if target interface has been intantiated") ;
else
this.intf = intf;
endfuction
task run () ;
this.drive () ;
endtask
task drive() ;
chnl_trans req,rsp;
@(posedge intf.rstn) ;
forever begin
this.req_mb. get(req);
this.chnl_write(req);
rsp = req. clone () ;
rsp.rsp = 1;
this.rsp_mb. put(rsp) ;
end
endtask
task chnl_write(input chnl_trans t);
foreach(t.data[i]) begin
@(posedge intf.clk);
intf.ch_valid <=1;
intf.ch_data <= t.data[i];
@(negedge intf.clk);
wait(intf.ch_ready === 'b1);
$display ("%0t channel initiator [%s] sent data %x",$time,name,t.data[i]);
repeat(t.data_nidles) chnl_idle() ;
end
repeat(t.pkt_nidles) chnl_idle() ;
endtask
task chnl_idle() ;
@(posedge intf.clk);
intf.ch_valid <=0;intf.ch_data <= 0;
endtask
endclass: chnl_initiator
class chnl _generator;
rand int pkt_id = -1;
rand int ch_id = -1;
rand int data_nidles = -1;
rand int pkt_nidles = -1;
rand int data_size = -1;
rand int ntrans = 10;
mailbox #(chnl_trans) req_mb;
mailbox #(chnl_trans) rsp_mb;
constraint cstr{
soft ch_id == -1;
soft pkt_id == -1;
soft data_size == -1;
soft data_nidles == -1;
soft pkt_nidles == -1;
soft ntrans == 10;}
function new () ;
this.req_mb = new ) ;
this.rsp_mb = new () ;
endfunction
task run () ;
repeat(ntrans) send_trans () ;run_stop_flags.put() ;
endtask
// generate transaction and put into local mailboxtask send_trans ) ;
chnl_trans req,rsp;
req = new() ;
assert(req.randomize with {local ::ch_id >= 0 -> ch_id == local ::ch_id;
local::pkt_id >= 0 -> pkt_id == local::pkt_id;
local::data_nidles >= 0 -> data_nidles == local : :data_nidles;
local::pkt_nidles >= 0 -> pkt_nidles == local:: pkt_nidles;
local::data_size >0 -> data.size() == local:: data_size;})
else $fatal(”[RNDFAIL] channel packet randomization failure! ");this.pkt_id++;
this.req_mb. put(req) ;
this.rsp_mb.get(rsp);
assert(rsp.rsp)
else $error(" [RSPFRR] %0t error resnonse receivedl" _$time)
endtask
endclass: chnl _generator