How to get virtual interface in sequence

In reply to sri205:

You NEVER want to drive any signal outside of your driver. This will result in multiple components driving signals which is a very bad idea. Only drive signals from your driver.

You can encapsulate your entire AXI transaction into a sequence item. When you do this, your driver will conduct all phases of the AXI transaction per the sequence item. Don’t have part of the transaction performed by the sequence and part by the driver.

In reply to sri205:

If you do not have a piplined approach implemented your sequencer is always waiting until you are calling item_done() ot put() in the driver, independently whether you are sending bac a response.
cgales doesn’t want you to modify your VIP, but using OOP inheritence you can extend your VIP transaction, thus defining a new sequence item which is VIP transaaction.

In reply to sri205:

It’s not really clear from your post what you are trying to accomplish.

Is the CPU being replaced by a UVM VIP? Is the CPU or IP protocol compliant by not waiting for a response or not supporting non-posted transactions.

If an IP block or verification component isn’t protocol compliant, then you have bigger issues that you need to address. If there are parts of the protocol that are optional and not supported, then your verification IP should allow for this.

Why is modifying the driver/monitor not an option? As a verification engineer, your job is to create the VIP necessary for your job. If it is third party VIP, then you need to work with your provider to determine how to handle any non-compliance issues.

In reply to sri205:

You have to differentiate between the sequence item/transaction data fields and the virtual interface. These are two completely different things. The signals of the AXI interface are defined. I guess you do not want to add more signals to this interface. Right?

In reply to sri205:

In reply to chr_sue:
Yes, I’ve not yet worked out the differentiation yet. actually the interface doesn’t have axi signals at all. it has open core protocol interface. Nevertheless, the scenario is the same i suppose. Can you point me to the example under cookbook examples which gives me the scenario i’m looking for under this link?

An Open Core Protocol Interface does not exist. I guess you are using an Open Core AXI interface, right? And I’m not sure if you want to replace the AXI RTL by the AXI VIP, because you have to drive the AXI RTL from an AXI VIP.
I believe you need a pipelined driver implementation. One of the cosing examples you can find here:
https://verificationacademy.com/cookbook/cookbook-code-examples#UVM_Examples:#UVM_Examples:#UVM_Examples:

Uvm_use_models_pipelined_get_put.tgz

In reply to sri205:

This was my mistake. I was assuming you were using an example from the Open Core Download page (http://opencores.org/)

In reply to sri205:
See below.
interface bus_if;
logic clk;
logic resetn;
logic[31:0] addr;
logic[31:0] write_data;
logic rnw;
logic valid;
logic ready;
logic[31:0] read_data;
logic error;
endinterface: bus_if

class bus_seq_item extends uvm_sequence_item;
// Request fields
rand logic[31:0] addr;
rand logic[31:0] write_data;
rand bit read_not_write;
rand int delay;

// Response fields
bit error;
logic[31:0] read_data;

endclass

In reply to sri205:

In the sequence item you do not have any control signals.
The intention for the interface and the sequence item is different. The interface has to drive the ports of your design. It is a pin-level interface.
The seq_item is provoding data necesary to drive the pin interface. In your case the seq_item has to have data members for addr, wrdata and rddata.

Hi,

I completely understand the part that sequence should not drive any signal.
But I am not very clear about the mistake in sampling a signal in a sequence instead of getting a response transaction from driver.

Although I get the difference that data item and component types of classes and so it is kind of “grammatically wrong” to access component variables inside data items.
Also being not of component type sequence will not have access to phasing.
But I thought p_sequencer is used for this purpose only.

So we can get interface handle in sequencer and from there to sequence perhaps.

I would like to have your further kind suggestions regarding this.

Regards,
Chandan

In reply to chandanc9:

One of the big benefits UVM is providing is the usage of TLM (transaction-level-modelling). It increases the performance of a UVM testbench dramatically and makes the processing of data very simple because it does not know clock and control signals. Processing is focused only on valuable data. All other aspects are removed on this level. If you deal with interface signals in sequnces you are loosing all these benfits and make the execution of sequences very complicated.
You should think about whether ist’s worth to do this.

In reply to chr_sue:

Thanks @chr_sue… I understand about abstraction level now…

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.