|
`include "uvm_pkg.sv" |
|
import uvm_pkg::*; |
|
|
|
typedef enum {PUSH_A,PUSH_B,ADD,SUB,MUL,DIV,POP_C} inst_e; |
|
|
|
//-----Packet/Transaction----- |
|
class my_seq_item extends uvm_sequence_item; |
|
rand inst_e inst; |
|
`uvm_object_utils_begin(my_seq_item) |
|
`uvm_field_enum(inst_e,inst, UVM_DEFAULT) |
|
`uvm_object_utils_end |
|
|
|
function new (string name = "my_seq_item"); |
|
super.new(name); |
|
endfunction : new |
|
|
|
function string convert2string(); |
|
convert2string = $sformatf("inst:%s", inst.name()); |
|
endfunction : convert2string |
|
endclass : my_seq_item |
|
|
|
//-----Sequencer----- |
|
class my_sequencer extends uvm_sequencer #(my_seq_item); |
|
`uvm_sequencer_utils(my_sequencer) |
|
|
|
function new (string name = "my_sequencer", uvm_component parent = null); |
|
super.new(name, parent); |
|
`uvm_update_sequence_lib_and_item(my_seq_item) |
|
endfunction : new |
|
endclass : my_sequencer |
|
|
|
//-----Driver----- |
|
class my_driver extends uvm_driver #(my_seq_item); |
|
`uvm_component_utils(my_driver) |
|
|
|
function new (string name = "my_driver", uvm_component parent = null); |
|
super.new(name, parent); |
|
endfunction : new |
|
|
|
task run_phase (uvm_phase phase); |
|
forever begin |
|
seq_item_port.get_next_item(req); |
|
`uvm_info(get_name(), $sformatf("Driving pkt %s", req.convert2string()), UVM_LOW) |
|
#10; |
|
seq_item_port.item_done(); |
|
end |
|
endtask : run_phase |
|
endclass : my_driver |
|
|
|
//-----Agent----- |
|
class my_agent extends uvm_agent; |
|
my_sequencer sqr; |
|
my_driver drv; |
|
`uvm_component_utils(my_agent) |
|
|
|
function new (string name = "my_agent", uvm_component parent = null); |
|
super.new(name, parent); |
|
endfunction : new |
|
|
|
function void build_phase (uvm_phase phase); |
|
super.build_phase(phase); |
|
sqr = my_sequencer::type_id::create("sqr", this); |
|
drv = my_driver::type_id::create("drv", this); |
|
endfunction : build_phase |
|
|
|
function void connect_phase (uvm_phase phase); |
|
super.connect_phase(phase); |
|
drv.seq_item_port.connect(sqr.seq_item_export); |
|
endfunction : connect_phase |
|
endclass : my_agent |
|
|
|
//-----Virtual Sequencer----- |
|
class my_virtual_sqr extends uvm_sequencer; |
|
my_sequencer sqr1; |
|
my_sequencer sqr2; |
|
`uvm_component_utils(my_virtual_sqr) |
|
|
|
function new (string name = "my_virtual_sqr", uvm_component parent = null); |
|
super.new(name, parent); |
|
endfunction : new |
|
endclass : my_virtual_sqr |
|
|
|
//-----seq_a----- |
|
class seq_a extends uvm_sequence #(my_seq_item); |
|
my_seq_item req; |
|
`uvm_object_utils(seq_a) |
|
|
|
function new(string name="seq_a"); |
|
super.new(name); |
|
endfunction : new |
|
|
|
virtual task body(); |
|
for (int unsigned i=0; i<4; i ++) begin |
|
`uvm_do_with(req, { inst == PUSH_A; }); |
|
`uvm_info(get_full_name(), $sformatf("completed :%0d iteration", i), UVM_LOW) |
|
end |
|
endtask : body |
|
endclass : seq_a |
|
|
|
//-----seq_b----- |
|
class seq_b extends uvm_sequence #(my_seq_item); |
|
my_seq_item req; |
|
`uvm_object_utils(seq_b) |
|
|
|
function new(string name="seq_b"); |
|
super.new(name); |
|
endfunction : new |
|
|
|
virtual task body(); |
|
for (int unsigned i=0; i<4; i ++) begin |
|
`uvm_do_with(req, { inst == PUSH_B; }); |
|
`uvm_info(get_full_name(), $sformatf("completed :%0d iteration", i), UVM_LOW) |
|
end |
|
endtask : body |
|
endclass : seq_b |
|
|
|
//-----seq_c----- |
|
class seq_c extends uvm_sequence #(my_seq_item); |
|
my_seq_item req; |
|
`uvm_object_utils(seq_c) |
|
|
|
function new(string name="seq_c"); |
|
super.new(name); |
|
endfunction : new |
|
|
|
virtual task body(); |
|
for (int unsigned i=0; i<4; i ++) begin |
|
`uvm_do_with(req, { inst == POP_C; }); |
|
`uvm_info(get_full_name(), $sformatf("completed :%0d iteration", i), UVM_LOW) |
|
end |
|
endtask : body |
|
endclass : seq_c |
|
|
|
//-----Virtual Sequence----- |
|
class parallel_sequence extends uvm_sequence #(my_seq_item); |
|
seq_a s_a; |
|
seq_b s_b; |
|
seq_c s_c; |
|
`uvm_object_utils(parallel_sequence) |
|
`uvm_declare_p_sequencer(my_virtual_sqr) |
|
|
|
function new(string name="parallel_sequence"); |
|
super.new(name); |
|
endfunction : new |
|
|
|
virtual task body(); |
|
grab(p_sequencer.sqr1); |
|
fork |
|
begin |
|
`uvm_create_on(s_a, p_sequencer.sqr1) |
|
`uvm_rand_send(s_a) |
|
`uvm_info(get_name(), $sformatf("s_a completed"), UVM_LOW) |
|
end |
|
begin |
|
`uvm_create_on(s_b, p_sequencer.sqr1) |
|
`uvm_rand_send(s_b) |
|
`uvm_info(get_name(), $sformatf("s_b completed"), UVM_LOW) |
|
end |
|
begin |
|
`uvm_create_on(s_c, p_sequencer.sqr2) |
|
`uvm_rand_send(s_c) |
|
`uvm_info(get_name(), $sformatf("s_c completed"), UVM_LOW) |
|
end |
|
join |
|
ungrab(p_sequencer.sqr1); |
|
endtask : body |
|
endclass : parallel_sequence |
|
|
|
//-----Virtual Sequence----- |
|
class parallel_sequence1 extends uvm_sequence #(my_seq_item); |
|
seq_a s_a; |
|
seq_b s_b; |
|
seq_c s_c; |
|
`uvm_object_utils(parallel_sequence1) |
|
`uvm_declare_p_sequencer(my_virtual_sqr) |
|
|
|
function new(string name="parallel_sequence1"); |
|
super.new(name); |
|
endfunction : new |
|
|
|
virtual task body(); |
|
fork |
|
begin |
|
`uvm_create_on(s_a, p_sequencer.sqr1) |
|
`uvm_rand_send(s_a) |
|
`uvm_info(get_name(), $sformatf("s_a completed"), UVM_LOW) |
|
end |
|
begin |
|
`uvm_create_on(s_b, p_sequencer.sqr1) |
|
`uvm_rand_send(s_b) |
|
`uvm_info(get_name(), $sformatf("s_b completed"), UVM_LOW) |
|
end |
|
begin |
|
`uvm_create_on(s_c, p_sequencer.sqr2) |
|
`uvm_rand_send(s_c) |
|
`uvm_info(get_name(), $sformatf("s_c completed"), UVM_LOW) |
|
end |
|
join |
|
endtask : body |
|
endclass : parallel_sequence1 |
|
|
|
//-----Test----- |
|
class my_test extends uvm_test; |
|
my_agent agent1; |
|
my_agent agent2; |
|
my_virtual_sqr vsqr; |
|
`uvm_component_utils(my_test) |
|
|
|
function new (string name = "my_test", uvm_component parent = null); |
|
super.new(name, parent); |
|
endfunction : new |
|
|
|
function void build_phase (uvm_phase phase); |
|
super.build_phase(phase); |
|
agent1 = my_agent::type_id::create("agent1", this); |
|
agent2 = my_agent::type_id::create("agent2", this); |
|
vsqr = my_virtual_sqr::type_id::create("vsqr", this); |
|
endfunction : build_phase |
|
|
|
function void connect_phase(uvm_phase phase); |
|
super.connect_phase(phase); |
|
vsqr.sqr1 = agent1.sqr; |
|
vsqr.sqr2 = agent2.sqr; |
|
endfunction : connect_phase |
|
|
|
task run_phase(uvm_phase phase); |
|
parallel_sequence p_seq; |
|
parallel_sequence1 p1_seq; |
|
p_seq = parallel_sequence::type_id::create("p_seq"); |
|
p1_seq = parallel_sequence1::type_id::create("p1_seq"); |
|
phase.raise_objection(this); |
|
fork |
|
p_seq.start(vsqr); |
|
p1_seq.start(vsqr); |
|
join |
|
phase.drop_objection(this); |
|
endtask : run_phase |
|
endclass : my_test |
|
|
|
module top(); |
|
initial begin |
|
run_test("my_test"); |
|
end |
|
endmodule : top |
|
|
|
// Output: |
|
// UVM_INFO grab_top_4.sv(42) @ 0: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(42) @ 0: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(128) @ 10: uvm_test_top.agent2.sqr@@p_seq.s_c [uvm_test_top.vsqr.p_seq.s_c] completed :0 iteration |
|
// UVM_INFO grab_top_4.sv(94) @ 10: uvm_test_top.agent1.sqr@@p_seq.s_a [uvm_test_top.vsqr.p_seq.s_a] completed :0 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 10: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(42) @ 10: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(111) @ 20: uvm_test_top.agent1.sqr@@p_seq.s_b [uvm_test_top.vsqr.p_seq.s_b] completed :0 iteration |
|
// UVM_INFO grab_top_4.sv(128) @ 20: uvm_test_top.agent2.sqr@@p1_seq.s_c [uvm_test_top.vsqr.p1_seq.s_c] completed :0 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 20: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(42) @ 20: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(128) @ 30: uvm_test_top.agent2.sqr@@p_seq.s_c [uvm_test_top.vsqr.p_seq.s_c] completed :1 iteration |
|
// UVM_INFO grab_top_4.sv(94) @ 30: uvm_test_top.agent1.sqr@@p_seq.s_a [uvm_test_top.vsqr.p_seq.s_a] completed :1 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 30: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(42) @ 30: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(111) @ 40: uvm_test_top.agent1.sqr@@p_seq.s_b [uvm_test_top.vsqr.p_seq.s_b] completed :1 iteration |
|
// UVM_INFO grab_top_4.sv(128) @ 40: uvm_test_top.agent2.sqr@@p1_seq.s_c [uvm_test_top.vsqr.p1_seq.s_c] completed :1 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 40: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(42) @ 40: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(128) @ 50: uvm_test_top.agent2.sqr@@p_seq.s_c [uvm_test_top.vsqr.p_seq.s_c] completed :2 iteration |
|
// UVM_INFO grab_top_4.sv(94) @ 50: uvm_test_top.agent1.sqr@@p_seq.s_a [uvm_test_top.vsqr.p_seq.s_a] completed :2 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 50: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(42) @ 50: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(111) @ 60: uvm_test_top.agent1.sqr@@p_seq.s_b [uvm_test_top.vsqr.p_seq.s_b] completed :2 iteration |
|
// UVM_INFO grab_top_4.sv(128) @ 60: uvm_test_top.agent2.sqr@@p1_seq.s_c [uvm_test_top.vsqr.p1_seq.s_c] completed :2 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 60: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(42) @ 60: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(128) @ 70: uvm_test_top.agent2.sqr@@p_seq.s_c [uvm_test_top.vsqr.p_seq.s_c] completed :3 iteration |
|
// UVM_INFO grab_top_4.sv(94) @ 70: uvm_test_top.agent1.sqr@@p_seq.s_a [uvm_test_top.vsqr.p_seq.s_a] completed :3 iteration |
|
// UVM_INFO grab_top_4.sv(161) @ 70: uvm_test_top.vsqr@@p_seq [p_seq] s_c completed |
|
// UVM_INFO grab_top_4.sv(151) @ 70: uvm_test_top.vsqr@@p_seq [p_seq] s_a completed |
|
// UVM_INFO grab_top_4.sv(42) @ 70: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(42) @ 70: uvm_test_top.agent2.drv [drv] Driving pkt inst:POP_C |
|
// UVM_INFO grab_top_4.sv(111) @ 80: uvm_test_top.agent1.sqr@@p_seq.s_b [uvm_test_top.vsqr.p_seq.s_b] completed :3 iteration |
|
// UVM_INFO grab_top_4.sv(128) @ 80: uvm_test_top.agent2.sqr@@p1_seq.s_c [uvm_test_top.vsqr.p1_seq.s_c] completed :3 iteration |
|
// UVM_INFO grab_top_4.sv(156) @ 80: uvm_test_top.vsqr@@p_seq [p_seq] s_b completed |
|
// UVM_INFO grab_top_4.sv(195) @ 80: uvm_test_top.vsqr@@p1_seq [p1_seq] s_c completed |
|
// UVM_INFO grab_top_4.sv(42) @ 80: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(94) @ 90: uvm_test_top.agent1.sqr@@p1_seq.s_a [uvm_test_top.vsqr.p1_seq.s_a] completed :0 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 90: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(111) @ 100: uvm_test_top.agent1.sqr@@p1_seq.s_b [uvm_test_top.vsqr.p1_seq.s_b] completed :0 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 100: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(94) @ 110: uvm_test_top.agent1.sqr@@p1_seq.s_a [uvm_test_top.vsqr.p1_seq.s_a] completed :1 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 110: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(111) @ 120: uvm_test_top.agent1.sqr@@p1_seq.s_b [uvm_test_top.vsqr.p1_seq.s_b] completed :1 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 120: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(94) @ 130: uvm_test_top.agent1.sqr@@p1_seq.s_a [uvm_test_top.vsqr.p1_seq.s_a] completed :2 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 130: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(111) @ 140: uvm_test_top.agent1.sqr@@p1_seq.s_b [uvm_test_top.vsqr.p1_seq.s_b] completed :2 iteration |
|
// UVM_INFO grab_top_4.sv(42) @ 140: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_A |
|
// UVM_INFO grab_top_4.sv(94) @ 150: uvm_test_top.agent1.sqr@@p1_seq.s_a [uvm_test_top.vsqr.p1_seq.s_a] completed :3 iteration |
|
// UVM_INFO grab_top_4.sv(185) @ 150: uvm_test_top.vsqr@@p1_seq [p1_seq] s_a completed |
|
// UVM_INFO grab_top_4.sv(42) @ 150: uvm_test_top.agent1.drv [drv] Driving pkt inst:PUSH_B |
|
// UVM_INFO grab_top_4.sv(111) @ 160: uvm_test_top.agent1.sqr@@p1_seq.s_b [uvm_test_top.vsqr.p1_seq.s_b] completed :3 iteration |
|
// UVM_INFO grab_top_4.sv(190) @ 160: uvm_test_top.vsqr@@p1_seq [p1_seq] s_b completed |