|HOME |ABOUT |ARTICLES |ACK |FEEDBACK |TOC |LINKS |BLOG |JOBS |


Tutorials



PHASE 6 DRIVER




In phase 6 we will write a driver and then insatiate the driver in environment and send packet in to DUT. Driver class is defined in Driver.sv file.

In this Driver class, take the packets from the generator and then drives it to the DUT input interface and then send the packet to a channel for scoreboard purpose.

In this class, we also add 2 callback methods.


1) Extend vmm_xactor_callbacks to define Driver_callbacks. In this class, declare 2 methods pre_trans() and post_trans(). pre_trans() method is called before driving the packet transaction and post_trans() method will be called after driving the packet transaction.


class Driver_callbacks extends vmm_xactor_callbacks;

// Called before a transaction is executed
virtual task pre_trans(Packet tr);
endtask: pre_trans

// Called after a transaction has been executed
virtual task post_trans(Packet tr);
endtask: post_trans

endclass:Driver_callbacks


1) Extend vmm_xactor to define Driver class.


class Driver extends vmm_xactor;


2) Declare a virtual input_interface of the switch. We will connect this to the Physical interface of the top module same as what we did in environment class.


virtual input_interface.IP input_intf;


3) Define a channel "gen2drv_chan" which is used to get packets from generator.


Packet_channel gen2drv_chan;


4) Define a channel "drv2sb_chan" which is used to send the packets to the score board.


Packet_channel drv2sb_chan;



4) Define new constructor with arguments, virtual input interface and channels "gen2drv_chan" and "drv2sb_chan".
In the constructor, call the parent constructor and pass the instance name and stream_id.
Connect the channel and virtual interfaces which are passed as constructor arguments to the class members.


function new(string inst,
int stream_id = -1,
virtual input_interface.IP input_intf_new,
Packet_channel gen2drv_chan = null,
Packet_channel drv2sb_chan = null);

super.new("driver",inst,stream_id);

this.input_intf = input_intf_new;

if(gen2drv_chan == null)
`vmm_fatal(log,"gen2drv_channel is null");
else
this.gen2drv_chan = gen2drv_chan;

if(drv2sb_chan == null)
`vmm_fatal(log,"drvr2sb_channel is null");
else
this.drv2sb_chan = drv2sb_chan;

`vmm_note(log,"Driver created ");
endfunction


4)Define drive() method. This method drives the packet to the dut.


task drive(Packet pkt);
logic [7:0] pack[];
int pkt_len;

pkt_len = pkt.byte_pack(pack,0,0);
@(posedge input_intf.clock);

for (int i=0;i< pkt_len - 1;i++)
begin
@(posedge input_intf.clock);
input_intf.cb.data_status <= 1 ;
input_intf.cb.data_in <= pack[i];
end

@(input_intf.clock);
input_intf.cb.data_status <= 0 ;
input_intf.cb.data_in <= pack[pkt_len -1];
@(input_intf.clock);
this.drv2sb_chan.put(pkt);
endtask



4) Define the main() method. First call the super.main() method.


super.main();
`vmm_note(this.log," started main task ");
5) In main() method, start a forever thread, which gets the packets from the 'gen2drv_chan' . The thread iteration has to be block if the channel is empty or stopped.


forever begin
Packet pkt;

wait_if_stopped_or_empty(this.gen2drv_chan);
this.gen2drv_chan.get(pkt);

`vmm_trace(this.log, "Starting transaction...");
`vmm_debug(this.log, pkt.psdisplay(" "));

6) Call the drive() method, which drives the packet to DUT. Call the pre_tans() call back method using `vmm_callback macro before calling the drive method and post_trans() callback method after driving the packet.

`vmm_callback(Driver_callbacks,pre_trans(pkt));

drive(pkt);

`vmm_callback(Driver_callbacks,post_trans(pkt));



Driver Class Source Code:



`ifndef GUARD_DRIVER
`define GUARD_DRIVER


class Driver_callbacks extends vmm_xactor_callbacks;

// Called before a transaction is executed
virtual task pre_trans(Packet tr);
endtask: pre_trans

// Called after a transaction has been executed
virtual task post_trans(Packet tr);
endtask: post_trans

endclass:Driver_callbacks



class Driver extends vmm_xactor;

virtual input_interface.IP input_intf;
Packet_channel gen2drv_chan;
Packet_channel drv2sb_chan;


function new(string inst,
int stream_id = -1,
virtual input_interface.IP input_intf_new,
Packet_channel gen2drv_chan = null,
Packet_channel drv2sb_chan = null);

super.new("driver",inst,stream_id);

this.input_intf = input_intf_new;

if(gen2drv_chan == null)
`vmm_fatal(log,"gen2drv_channel is null");
else
this.gen2drv_chan = gen2drv_chan;

if(drv2sb_chan == null)
`vmm_fatal(log,"drvr2sb_channel is null");
else
this.drv2sb_chan = drv2sb_chan;

`vmm_note(log,"Driver created ");
endfunction

task drive(Packet pkt);
logic [7:0] pack[];
int pkt_len;

pkt_len = pkt.byte_pack(pack,0,0);
@(posedge input_intf.clock);

for (int i=0;i< pkt_len - 1;i++)
begin
@(posedge input_intf.clock);
input_intf.cb.data_status <= 1 ;
input_intf.cb.data_in <= pack[i];
end

@(input_intf.clock);
input_intf.cb.data_status <= 0 ;
input_intf.cb.data_in <= pack[pkt_len -1];
@(input_intf.clock);
this.drv2sb_chan.put(pkt);
endtask


task main();
super.main();
`vmm_note(this.log," started main task ");

forever begin
Packet pkt;

wait_if_stopped_or_empty(this.gen2drv_chan);
this.gen2drv_chan.get(pkt);

`vmm_trace(this.log, "Starting transaction...");
`vmm_debug(this.log, pkt.psdisplay(" "));

`vmm_callback(Driver_callbacks,pre_trans(pkt));

drive(pkt);

`vmm_callback(Driver_callbacks,post_trans(pkt));

`vmm_trace(this.log, "Completed transaction...");
`vmm_debug(this.log, pkt.psdisplay(" "));
@(posedge input_intf.clock);

end
endtask

endclass
`endif



Now we will take the instance of the driver in the environment class.




1) Declare a channel "drvr2sb_chan" which will be used to connect the scoreboard and driver.


Packet_channel drvr2sb_chan;


2) Declare a driver object "drvr".


Driver drvr;


3) In build method, construct the channel.


drvr2sb_chan = new("drvr2sb","chan");


4) In build method, construct the driver object. Pass the input_intf and drvr2sb_chan channel and gen2drvr_chan channel.


drvr = new("Drvr",0,input_intf,gen2drvr_chan,drvr2sb_chan);


5) To start sending the packets to the DUT, call the start method of "drvr" in the start method of Environment class.


drvr.start();


5)In the stop() method, call the stop_xactor() method of drvr.


drvr.stop_xactor();


Environment Class Source Code:


`ifndef GUARD_ENV
`define GUARD_ENV

class Environment extends vmm_env;

virtual mem_interface.MEM mem_intf ;
virtual input_interface.IP input_intf ;
virtual output_interface.OP output_intf[4] ;

Packet_atomic_gen atomic_gen;

Driver drvr;

Packet_channel gen2drvr_chan;

Packet_channel drvr2sb_chan;

function new(virtual mem_interface.MEM mem_intf_new ,
virtual input_interface.IP input_intf_new ,
virtual output_interface.OP output_intf_new[4] );
super.new("Environment ");
this.mem_intf = mem_intf_new ;
this.input_intf = input_intf_new ;
this.output_intf = output_intf_new ;

`vmm_note(this.log, "Created env object");
endfunction : new


virtual function void gen_cfg();
super.gen_cfg();
`vmm_note(this.log,"Start of gen_cfg() method ");
`vmm_note(this.log,"End of gen_cfg() method ");
endfunction
virtual function void build();
super.build();
`vmm_note(this.log,"Start of build() method ");
gen2drvr_chan = new("gen2drvr","chan");

drvr2sb_chan = new("drvr2sb","chan");
drvr = new("Drvr",0,input_intf,gen2drvr_chan,drvr2sb_chan);

atomic_gen = new("atomic_gen",0,gen2drvr_chan);
atomic_gen.stop_after_n_insts = 10;
`vmm_note(this.log,"End of build() method ");
endfunction

virtual task reset_dut();
super.reset_dut();
`vmm_note(this.log,"Start of reset_dut() method ");
mem_intf.cb.mem_data <= 0;
mem_intf.cb.mem_add <= 0;
mem_intf.cb.mem_en <= 0;
mem_intf.cb.mem_rd_wr <= 0;
input_intf.cb.data_in <= 0;
input_intf.cb.data_status <= 0;
output_intf[0].cb.read <= 0;
output_intf[1].cb.read <= 0;
output_intf[2].cb.read <= 0;
output_intf[3].cb.read <= 0;

// Reset the DUT
input_intf.reset <= 1;
repeat (4) @ input_intf.clock;
input_intf.reset <= 0;

`vmm_note(this.log,"End of reset_dut() method ");
endtask

virtual task cfg_dut();
super.cfg_dut();
`vmm_note(this.log,"Start of cfg_dut() method ");
mem_intf.cb.mem_en <= 1;
@(posedge mem_intf.clock);
mem_intf.cb.mem_rd_wr <= 1;

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h0;
mem_intf.cb.mem_data <= `P0;
`vmm_note(this.log ,$psprintf(" Port 0 Address %h ",`P0));

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h1;
mem_intf.cb.mem_data <= `P1;
`vmm_note(this.log ,$psprintf(" Port 1 Address %h ",`P1));

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h2;
mem_intf.cb.mem_data <= `P2;
`vmm_note(this.log ,$psprintf(" Port 2 Address %h ",`P2));

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h3;
mem_intf.cb.mem_data <= `P3;
`vmm_note(this.log ,$psprintf(" Port 3 Address %h ",`P3));

@(posedge mem_intf.clock);
mem_intf.cb.mem_en <=0;
mem_intf.cb.mem_rd_wr <= 0;
mem_intf.cb.mem_add <= 0;
mem_intf.cb.mem_data <= 0;

`vmm_note(this.log,"End of cfg_dut() method ");
endtask

virtual task start();
super.start();
`vmm_note(this.log,"Start of start() method ");
atomic_gen.start_xactor();

drvr.start_xactor();

`vmm_note(this.log,"End of start() method ");
endtask

virtual task wait_for_end();
super.wait_for_end();
`vmm_note(this.log,"Start of wait_for_end() method ");
repeat(1000) @(input_intf.clock);
`vmm_note(this.log,"End of wait_for_end() method ");
endtask

virtual task stop();
super.stop();
`vmm_note(this.log,"Start of stop() method ");
atomic_gen.stop_xactor();

drvr.stop_xactor();

`vmm_note(this.log,"End of stop() method ");
endtask

virtual task cleanup();
super.cleanup();
`vmm_note(this.log,"Start of cleanup() method ");
`vmm_note(this.log,"End of cleanup() method ");
endtask

virtual task report();
`vmm_note(this.log,"Start of report() method \n\n\n");
$display("---------------------------------------------------------------------");
super.report();
$display("---------------------------------------------------------------------");
$display("\n\n");
`vmm_note(this.log,"End of report() method");
endtask

endclass
`endif

(S)Download the phase 6 source code:


vmm_switch_6.tar
Browse the code in vmm_switch_6.tar


(S)Run the command:
vcs -sverilog -f filelist -R -ntb_opts rvm

(S)Log file report.

******************* Start of testcase ****************
Normal[NOTE] on Environemnt() at 0:
Created env object
Normal[NOTE] on Environemnt() at 0:
Start of gen_cfg() method
Normal[NOTE] on Environemnt() at 0:
End of gen_cfg() method
Normal[NOTE] on Environemnt() at 0:
Start of build() method
Normal[NOTE] on driver(Drvr) at 0:
Driver created
Normal[NOTE] on Environemnt() at 0:
End of build() method
Normal[NOTE] on Environemnt() at 0:
Start of reset_dut() method
Normal[NOTE] on Environemnt() at 60:
End of reset_dut() method
Normal[NOTE] on Environemnt() at 60:
Start of cfg_dut() method
Normal[NOTE] on Environemnt() at 90:
Port 0 Address 00
Normal[NOTE] on Environemnt() at 110:
Port 1 Address 11
Normal[NOTE] on Environemnt() at 130:
Port 2 Address 22
Normal[NOTE] on Environemnt() at 150:
Port 3 Address 33
Normal[NOTE] on Environemnt() at 170:
End of cfg_dut() method
Normal[NOTE] on Environemnt() at 170:
Start of start() method
Normal[NOTE] on Environemnt() at 170:
End of start() method
Normal[NOTE] on Environemnt() at 170:
Start of wait_for_end() method
Normal[NOTE] on driver(Drvr) at 170:
started main task
Normal[NOTE] on Environemnt() at 10170:
End of wait_for_end() method
Normal[NOTE] on Environemnt() at 10170:
Start of stop() method
Normal[NOTE] on Environemnt() at 10170:
End of stop() method
Normal[NOTE] on Environemnt() at 10170:
Start of cleanup() method
Normal[NOTE] on Environemnt() at 10170:
End of cleanup() method
Normal[NOTE] on Environemnt() at 10170:
Start of report() method



---------------------------------------------------------------------
Simulation PASSED on /./ (/./) at 10170 (0 warnings, 0 demoted errors & 0 demoted warnings)
---------------------------------------------------------------------



Normal[NOTE] on Environemnt() at 10170:
End of report() method
******************** End of testcase *****************

Index
Introduction
Specification
Verification Plan
Phase 1 Top
Phase 2 Environment
Phase 3 Reset
Phase 4 Packet
Phase 5 Generator
Phase 6 Driver
Phase 7 Receiver
Phase 8 Scoreboard
Phase 9 Coverage

Report a Bug or Comment on This section - Your input is what keeps Testbench.in improving with time!





<< PREVIOUS PAGE

TOP

NEXT PAGE >>

copyright 2007-2017 :: all rights reserved www.testbench.in::Disclaimer