How to get virtual interface in sequence

In reply to chr_sue:


class vseq_sandbox extends uvm_sequence #(uvm_sequence_item);
  `uvm_object_utils(vseq_sandbox);

  virtual interface cool_if my_if; // assigned by test

  function new(string name="");
    super.new(name);
  endfunction

  virtual task body();
    my_if.wait_clks(10);
  endtask

endclass

This is very straight-forward, but violates the principles of TLM. thoughts?

Guyz, instead of using virtual interface in a sequence , why cant we create a polling sequence which eventually will grab the interface bus status(in driver) .

This polling sequence can be called whenever you want the status of any pin in DUT.

Any issue in this?

Thanks,
Suyog

In reply to bmorris:

In reply to chr_sue:


class vseq_sandbox extends uvm_sequence #(uvm_sequence_item);
`uvm_object_utils(vseq_sandbox);
virtual interface cool_if my_if; // assigned by test
function new(string name="");
super.new(name);
endfunction
virtual task body();
my_if.wait_clks(10);
endtask
endclass

This is very straight-forward, but violates the principles of TLM. thoughts?

This is not a question of violating rules. You are loosing the benfits of TLM. TLM is an untimed modelling style. TLM does not know about clock cycles it knows only the right order of commands. Finally it behaves like a piece of software.

In reply to chr_sue:

Personally, I’ve tried using TLM for these kinds of operations, and it’s always clunky and bloated.

Lets say I’ve got a sequence, and the very first thing it has to do is wait for the DUT to initialize. This happens at 7ms.

I could…

  1. Just have the seq wait 7.5 ms, then start.
  2. Use a virtual interface to detect a DUT signal going high (assuming it exists)
  3. Go make a new transaction, agent, the previous interface, detect that init is done, broadcast the transaction, somehow connect this to the sequence? All in the name of TLM?

I think a better approach would be to use TLM for things it is good at, and VI for what it’s good at.

In reply to bmorris:

For dealing with TLM you need a completely different thinking, which is not timed.
It is not true that you have to wait a certain time for processing a sequence. You can start the sequence at time 0. The timing is in the driver. The driver blocks any seq_item generation until the first get/get_next_item.

In reply to chr_sue:

Yes, I understand what you are saying. Isolate the pin interactions to the transactors.
Delays are no problem.

It gets a little more strange when the sequence needs to wait on some oddball register that has nothing to do with the interface in question.

Or, the transaction (say, a UDP packet) is being passed through several layering agents, so by the time it gets down to the lowest pin-level activity, it supposed to know to wait on some signal before pumping in bytes?

udp_txn_t txn = udp_txn_t::type_id::create("txn");

<------- TLM: what am I going to put here to get my driver to wait for the DUT to 
         wait until it's initialized before driving the pins?  You can assume there's a 
         register, or even a pin that asserts when init is done.

start_item(txn);
finish_item(txn);

In reply to bmorris:

If you have to consider a register value you can access this register through the register layer. It’s very simple and powerful.
I don’t understand what you mean with layered agents. You might have layered sequences, i.e a high lever sequnence which is passing high level data to a low level sequence. This works also fine without haveing any time-dependency. If the driver has to wait for any reason no additional seq_item (high and low level) will be generated until the current item has been completed.

In reply to chr_sue:

I think we are talking about the same thing.
https://verificationacademy.com/cookbook/sequences/layering

I agree, there is no time dependency. I’m just saying that interactions with the DUT that don’t have any association to the interface in question should not be handled by that agent. I.e. I shouldnt be putting fields into my UDP packet transaction like “bit wait_on_init”. It doesn’t know anything about that, nor should it. Putting a delay in, sure thats perfectly normal.


Sure, I can use the RAL to access a register, but I would have to poll it. That means I need a delay. How would you delay here (using TLM)? I’m guessing that answer is to create a “system” transaction, and start that on a “system” agent, where the interface will expend clock cycles. you agree?

// sequence
virtual task body();

  while (data==0) begin
    <------ need to delay here
    dut_ral.ctrl_reg.read(.status(status), .value(data), .parent(this));
  end

endtask

In reply to bmorris:

Initiating a read as you do is the most complicated way to access a register, because iut initiates a bus cycle and you do not really use the benefit of the register layer. A smarter way would be to perform a peek. But the best way is directly accees the register, because it has a fixed position in the hierarchy of the UVM environment.