This is my code to verify a switch.
A note of caution when using mailbox, mailbox only holds handles not the object. So if you need to place multiple objects in the mailbox simultaneously, you would need to create (new) objects equivalent number of times.
class packet;
rand bit [47:0] src_addr;
rand bit [31:0] src_data;
//signal unrelated to rtl
static bit [15:0] pkt_id;
//packet class is no longer talking to RTL, so no need of VI
function new();
pkt_id++;
endfunction
virtual function void print();
$display("src_addr = %h, src_data = %h", src_addr, src_data);
endfunction
virtual function void rec_print();
$display("dst_addr = %h, dst_data = %h", src_addr, src_data);
endfunction
virtual function packet deepcopy();
//$display("I am here: in deepcopy in packet class");
packet funny;
funny = new();
return(funny);
endfunction
endclass
///////////////////////////////////////////////////////////////////////
class transaction extends packet;
virtual function packet deepcopy(); //has to match prototype
packet pkt_deepcopy;
pkt_deepcopy = new();
pkt_deepcopy.src_data = this.src_data;
pkt_deepcopy.src_addr = this.src_addr;
return(pkt_deepcopy);
endfunction
//function pack();
//function unpack();
endclass
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// driver must be container class to talk to class packet, class sb
class driver;
packet pkt;
virtual switch_interface vi;
mailbox drv2sb;
function new(input virtual switch_interface vif, input mailbox mb);
this.vi = vif;
this.drv2sb = mb;
endfunction
task send_packet();
pkt = new();
assert(pkt.randomize());
@(posedge vi.clk);
vi.src_addr <= pkt.src_addr;
@(posedge vi.clk);
vi.src_data <= pkt.src_data;
pkt.print();
drv2sb.put(pkt);
endtask
endclass
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class monitor;
virtual switch_interface mi;
packet rcv_pkt;
mailbox mon2sb;
function new(input virtual switch_interface mif, input mailbox mb);
this.mi = mif;
this.mon2sb = mb;
endfunction
task collect_packet();
rcv_pkt = new();
@(posedge mi.clk);
rcv_pkt.src_addr = mi.cb.dst_addr;
@(posedge mi.clk);
rcv_pkt.src_data = mi.cb.dst_data;
rcv_pkt.rec_print();
mon2sb.put(rcv_pkt);
endtask
endclass
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class scoreboard;
mailbox rcv_from_drv;
mailbox rcv_from_mon;
function new(input mailbox drv2sb, input mailbox mon2sb);
this.rcv_from_drv = drv2sb;
this.rcv_from_mon = mon2sb;
endfunction
task compare (input mailbox rcv_from_drv, input mailbox rcv_from_mon);
bit error;
packet pkt_from_drv;
packet pkt_from_mon;
rcv_from_drv.get(pkt_from_drv);
rcv_from_mon.get(pkt_from_mon);
pkt_from_drv.print();
pkt_from_mon.rec_print();
if (pkt_from_mon.src_addr !== (pkt_from_drv.src_addr + 1)) begin
$display("time=%0t ERROR: Packet Mismatch, wrong addr", $time);
error++;
end
else if (pkt_from_mon.src_data !== (pkt_from_drv.src_data + 1)) begin
$display("time=%0t ERROR: Packet Mismatch, wrong data", $time);
error++;
end
else $display("time=%0t PASS: Packet Match", $time);
endtask
endclass
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
class env;
driver drv;
monitor mon;
virtual switch_interface vi;
virtual switch_interface mi;
//add sb n mailbox to env neighbourbood
scoreboard sb;
mailbox drv2sb;
mailbox mon2sb;
function new(input virtual switch_interface vif, input virtual switch_interface mif);
this.vi = vif;
this.mi = mif;
//create objects (data members)
drv2sb = new();
mon2sb = new();
//hand over drv2sb to drv + sb, and mon2sb to mon + sb
drv = new(vif, drv2sb);
mon = new(mif, mon2sb);
sb = new(drv2sb, mon2sb);
endfunction
//env directs driver to send wiggle through run task
task run(input int count_packet);
for(int i=0; i <count_packet; i++) begin
@(posedge vi.clk) drv.send_packet();
@(posedge mi.clk) mon.collect_packet();
sb.compare(drv2sb, mon2sb);
end
endtask
endclass
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`include "packet6.sv"
program testcase(switch_interface tcifdriver, switch_interface tcifmonitor);
/*class packet_fixed_src_data extends packet;
constraint fixed_src_data { src_data == 32'hbabeface;
}
endclass*/
env env0;
int num_packet;
//packet_fixed_src_data testcasepacket;
packet pkt;
packet deep;
transaction deep_base;
initial begin
env0 = new(tcifdriver, tcifmonitor);
num_packet=$urandom_range(4,32);
//env0.run(num_packet);
pkt = new();
assert(pkt.randomize());
$display("Printing pkt");
pkt.print();
deep = new();
deep = pkt.deepcopy();
$display("Printing deep, after deepcopy from packetclass (just a template function, doesnt actually perform deepcopy)");
deep.print();
deep_base = new();
assert(deep_base.randomize());
$display("Printing deep_base");
deep_base.print();
deep = deep_base.deepcopy();
$display("Printing deep, after deepcopy from extended class");
deep.print();
#100 $finish;
end
endprogram
A note of caution when using mailbox, mailbox only holds handles not the object. So if you need to place multiple objects in the mailbox simultaneously, you would need to create (new) objects equivalent number of times.
class packet;
rand bit [47:0] src_addr;
rand bit [31:0] src_data;
//signal unrelated to rtl
static bit [15:0] pkt_id;
//packet class is no longer talking to RTL, so no need of VI
function new();
pkt_id++;
endfunction
virtual function void print();
$display("src_addr = %h, src_data = %h", src_addr, src_data);
endfunction
virtual function void rec_print();
$display("dst_addr = %h, dst_data = %h", src_addr, src_data);
endfunction
virtual function packet deepcopy();
//$display("I am here: in deepcopy in packet class");
packet funny;
funny = new();
return(funny);
endfunction
endclass
///////////////////////////////////////////////////////////////////////
class transaction extends packet;
virtual function packet deepcopy(); //has to match prototype
packet pkt_deepcopy;
pkt_deepcopy = new();
pkt_deepcopy.src_data = this.src_data;
pkt_deepcopy.src_addr = this.src_addr;
return(pkt_deepcopy);
endfunction
//function pack();
//function unpack();
endclass
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// driver must be container class to talk to class packet, class sb
class driver;
packet pkt;
virtual switch_interface vi;
mailbox drv2sb;
function new(input virtual switch_interface vif, input mailbox mb);
this.vi = vif;
this.drv2sb = mb;
endfunction
task send_packet();
pkt = new();
assert(pkt.randomize());
@(posedge vi.clk);
vi.src_addr <= pkt.src_addr;
@(posedge vi.clk);
vi.src_data <= pkt.src_data;
pkt.print();
drv2sb.put(pkt);
endtask
endclass
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class monitor;
virtual switch_interface mi;
packet rcv_pkt;
mailbox mon2sb;
function new(input virtual switch_interface mif, input mailbox mb);
this.mi = mif;
this.mon2sb = mb;
endfunction
task collect_packet();
rcv_pkt = new();
@(posedge mi.clk);
rcv_pkt.src_addr = mi.cb.dst_addr;
@(posedge mi.clk);
rcv_pkt.src_data = mi.cb.dst_data;
rcv_pkt.rec_print();
mon2sb.put(rcv_pkt);
endtask
endclass
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class scoreboard;
mailbox rcv_from_drv;
mailbox rcv_from_mon;
function new(input mailbox drv2sb, input mailbox mon2sb);
this.rcv_from_drv = drv2sb;
this.rcv_from_mon = mon2sb;
endfunction
task compare (input mailbox rcv_from_drv, input mailbox rcv_from_mon);
bit error;
packet pkt_from_drv;
packet pkt_from_mon;
rcv_from_drv.get(pkt_from_drv);
rcv_from_mon.get(pkt_from_mon);
pkt_from_drv.print();
pkt_from_mon.rec_print();
if (pkt_from_mon.src_addr !== (pkt_from_drv.src_addr + 1)) begin
$display("time=%0t ERROR: Packet Mismatch, wrong addr", $time);
error++;
end
else if (pkt_from_mon.src_data !== (pkt_from_drv.src_data + 1)) begin
$display("time=%0t ERROR: Packet Mismatch, wrong data", $time);
error++;
end
else $display("time=%0t PASS: Packet Match", $time);
endtask
endclass
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
class env;
driver drv;
monitor mon;
virtual switch_interface vi;
virtual switch_interface mi;
//add sb n mailbox to env neighbourbood
scoreboard sb;
mailbox drv2sb;
mailbox mon2sb;
function new(input virtual switch_interface vif, input virtual switch_interface mif);
this.vi = vif;
this.mi = mif;
//create objects (data members)
drv2sb = new();
mon2sb = new();
//hand over drv2sb to drv + sb, and mon2sb to mon + sb
drv = new(vif, drv2sb);
mon = new(mif, mon2sb);
sb = new(drv2sb, mon2sb);
endfunction
//env directs driver to send wiggle through run task
task run(input int count_packet);
for(int i=0; i <count_packet; i++) begin
@(posedge vi.clk) drv.send_packet();
@(posedge mi.clk) mon.collect_packet();
sb.compare(drv2sb, mon2sb);
end
endtask
endclass
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`include "packet6.sv"
program testcase(switch_interface tcifdriver, switch_interface tcifmonitor);
/*class packet_fixed_src_data extends packet;
constraint fixed_src_data { src_data == 32'hbabeface;
}
endclass*/
env env0;
int num_packet;
//packet_fixed_src_data testcasepacket;
packet pkt;
packet deep;
transaction deep_base;
initial begin
env0 = new(tcifdriver, tcifmonitor);
num_packet=$urandom_range(4,32);
//env0.run(num_packet);
pkt = new();
assert(pkt.randomize());
$display("Printing pkt");
pkt.print();
deep = new();
deep = pkt.deepcopy();
$display("Printing deep, after deepcopy from packetclass (just a template function, doesnt actually perform deepcopy)");
deep.print();
deep_base = new();
assert(deep_base.randomize());
$display("Printing deep_base");
deep_base.print();
deep = deep_base.deepcopy();
$display("Printing deep, after deepcopy from extended class");
deep.print();
#100 $finish;
end
endprogram
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
module testbench();
bit [47:0] dst_addr;
bit [31:0] dst_data;
bit clk;
bit sop, eop;
bit valid;
always #10 clk = ~clk;
switch_interface sif (.clk (clk));
switch sw0 (
.clk (clk),
.src_addr (sif.src_addr),
.src_data (sif.src_data),
.dst_addr (sif.dst_addr), //monitor
.dst_data (sif.dst_data)
);
testcase itest (.tcifdriver (sif.testcase_port),
.tcifmonitor (sif.testcase_port));
endmodule
No comments:
Post a Comment