Create a task() that can be called in the test sequence

Hi,

I am trying to create a task and name it mem_wr() and passing in the addr and wdata to this task, then in this task I need to do the following

*typedef apb3_host_write #(SLAVE_COUNT, ADDRESS_WIDTH, WDATA_WIDTH, RDATA_WIDTH) write_item_t;

    write_item_t write_item = write_item_t::type_id::create("write_item");

    write_item.addr=addr;
    write_item.wr_data=wdata;
    start_item(write_item);
    finish_item(write_item);*

Basically the objective is to reduce the number of lines for initiate a transaction from APB master BFM to my design. By doing this I can just write something like this to initiate a transaction, instead of writing 4 lines of code

    *mem_wr('h04, 'hFFFF0000;*

I understand that to use the start_item() and finish_item(), it must be done within ovm_object or ovm_sequence_item. May I know how to code this thing out and how to use it in my test sequence and where should I import/include this class?

Thanks!

-Eric-

Excellent objective, Eric. There is not much to it–in fact you have most of the “guts” to what the task would look like. Start_item and finish_item are methods of the uvm_sequence #() class, so you must call them via a sequence handle or from within a uvm_sequence extension.

One solution would be to write a base sequence class that contains the mem_wr and any other convenience methods, then have your test sequences extend from that base class:

class my_sequence_base extends uvm_sequence #(write_item_t);
  `uvm_object_utils(my_sequence_base)
  task mem_wr(addr_t addr, data_t data);
    write_item_t write_item = write_item_t::type_id::create("write_item");
    write_item.addr=addr;
    write_item.wr_data=wdata;
    start_item(write_item);
    finish_item(write_item);
  endtask
  task mem_rd(addr_t addr, output data_t data);
    ...
  endtask
endclass

Then test sequences could extend from this base and call the inherited convenience methods:

class write_seq extends my_sequence_base;
  `uvm_object_utils(write_seq)
  task body();
    mem_wr('h1000, 'h1234);
    mem_wr('h1004, 'h5678);
    ...
  endtask
endclass

To give you one more alternative, you could instead encapsulate the write task in a static method of a utilities class. This lets you write test sequences that do not have to inherit from a base sequence class.

class my_bus_utils;
   static task mem_wr(addr_t addr, data_t data, uvm_sequence_base seq);
     ...same as above except use seq handle to start/finish:
     seq.start_item(write_item);
     seq.finish_item(write_item);
   endtask
endclass

The test sequence would then use the above utility class as follows:

class write_seq extends uvm_sequence #(...);
  `uvm_object_utils(write_seq)
  task body();
    my_bus_utils::mem_wr('h1000, 'h1234, this);
    my_bus_utils::mem_wr('h1004, 'h5678, this);
    ...
  endtask
endclass

In reply to Adam:

Thanks Adam for the suggestion.

I’m pretty new in the OVM and system verilog, so I might be asking simple questions.

My verification environment is having a base_test (extends from ovm_test) and it does the BFM configuration work. In my test sequence, it has two classes, which are

class testing extends base_test;

testing seq_t;
task run();
seq_t seq=seq_t::type_id::create(“seq_t seq”);
super.run();
seq.start(env.m_agent.sequencer);
global_stop_request();
endclass

class testing_seq extends mstr_sequence;
function new (…)
virtual task body;

mem_wr('hAB, 'hBEEF);
endtask
endclass

I am following your suggestion code the task() as following

class mem_cyc extends ovm_sequence # (ovm_sequence_item);
`ovm_object_utils (mem_cyc);

typedef apb3_host_write    #(SLAVE_COUNT, ADDRESS_WIDTH, WDATA_WIDTH, RDATA_WIDTH) write_item_t;

task mem_wr (bit [15:0] addr, bit [31:0] wdata);
    write_item_t write_item = write_item_t::type_id::create("write_item");
    write_item.addr=addr;
    write_item.wr_data=wdata;
    start_item(write_item);
    finish_item(write_item);
endtask

endclass : mem_cyc

I tried to `include the mem_cyc.svh in the base_test, compile error with this message
** Error: tests/testing.svh(78): (vlog-7027) Dotted name (‘mem_wr’) not found in current scope. Note that hierarchical references are not allowed from within a package or $unit.

I tried to `include it in the test sequence (testing.svh), same error pops up.

May I know what is wrong with the coding?
I’m thinking that can I have the task() embedded in my base_test? How should I do that?

Appreciate with your help!!!

-Eric-

In reply to ericew:

First, your testing class needs a little fixing. I think this is what you mean to do:

class testing extends base_test; ... task run(); testing_seq seq=seq_t::type_id::create("seq"); super.run(); seq.start(env.m_agent.sequencer); global_stop_request(); endtask endclass

Now, if you define the mem_wr task in a base sequence, your test sequence must extend from that base sequence if it is to “see” the mem_wr task. Your test sequence extends mstr_sequence, not mem_cyc, hence the compiler error.

class testing_seq extends mem_cyc; // <<---- extends mem_cyc function new (....) virtual task body; ... mem_wr('hAB, 'hBEEF); endtask endclass

Adam

In reply to Adam:

Thanks Adam, it works perfectly, that is exactly what I need!!!

Thanks again!

-Eric-