Sign in to follow this  
Followers 0
preet723

packet transactions are generated by scheduler, need help with sequence class

8 posts in this topic

Hi there,

Please help me on this problem. I am still learning UVM.

I have transaction type "Packet", which is generated by combining different data types like for example

Packet = {D0, D8, D7, D1, D1, D7,D0,D8} where D0, D8, D7, D1 are different data types derived from same base class.

Packet is formed when there are 8 such data types available and generation of all these data types is controlled by RATE SCHEDULER specified by user. At very low rates, packets will be formed after long time.

At times there many not be any Data type, and hence no packet can drive to driver.

In VMM it was easy, whenever Packet was formed, i would push it to driver by using channel. Else nothing is driven.

In UVM, i am not getting how to do.

Below, how should i write body task.

1) I can't have specific number in repeat () because packets are generated on fly by the scheduler.

2) I can't have packets in queue [$], and use for loop in task body, because queue size will keep on changing.

3) What will happen if i call uvm_do(req) macro, but there is no actual packet formed at that point.

class packet_sequence extends uvm_sequence #(packet);

/// taking out new function etc

virtual task body();

// raise objection

repeat(10) begin <-----------------

`uvm_do(req);

end

// drop objection

Please help me in understanding a bit.

thanks.

Share this post


Link to post
Share on other sites

You can avoid the repeat by using other kinds of loops like while or for, then you can set another kind of exit to the loop, like a flag. In case you have more than one sequence running on the chip, you can synchronize them with a higher level virtual sequence which can set the flag to end the loop.

One way of creating delays between packets is to have a variable in the packet which tells the driver to wait for x clock cycles before send the packet to the pins. Then the sequencer and the sequence will halt while the driver is not requesting new packets. In case the delays are not available at the start of the packet, you could create a flag to identify packets that do only the waiting and skip driving the output.

If you call the uvm_do, it will randomize the rand variables and send to the driver what it has. In case it is not the wanted behavior because the packet is not ready, I would create an error message in the driver to help implementing the wait clk cycles feature.

I hope this was helpful.

Share this post


Link to post
Share on other sites

Thanks a ton, Whiteriver for your prompt reply. Thanks.

After a daylong thinking, I have come up with following logic.

Please provide your feedback and let me know if I am thinking right, anything that I might be missing.

Also I do have some doubts about the code. I have asked Qs in RED along with my thinking process.

/******** C1 -- data classes ***********/

1) Consists of all the constraints of what contents each data type D0-D8 should contain, and weight distribution given to each data type. Also consists of covergroups.

2) Base class derived from uvm_sequence_item;

----------------------------------------------

/******** C2 - data rate scheduler class ******/

1) This class should be derived from where ???? uvm_sequence_item ??

Should I derive this class from uvm_sequence_item, even though it is not a data type ??

2) Factory create 9 queues for each of data types D0-D8

Using factory create method, is this right way ??

3) Implements rate scheduling logic along with constraints to generate data types based on user defined values and pushes them to their respective queue.

4) Also implements logic on extracting back data types from their respective queues.

5) In post_configure phase enable rate_schedular, call randomize (), so that it randomizes the data items and constraint are applied. At this point it will start generating data types.

What should I do so that every time data items are generated they are randomized and proper constraints are applied. Would single call to randomize() work ??-------------------------------------------

/******** C3 - packet class *************/

1) Class packet extends uvm_sequence_item;

2) Factory create array of type data class of size 8, to fit in 8 consecutive data types in packet

3) Consists of random flags for different types of packet corruption

4) Constraints and cover groups of the order of how data types D0-D8 should fit in packet.

5) Function to add data type to packet “add_one_dataâ€

-------------------------------------------

/********** C4 – sequence class **************/

`include C1, C2, C3 // include all classes: data, data scheduler, packet classes

1) Class packet_sequence extends uvm_sequence # (packet);

2) Include random variables and constraints to specify how many data types 0-8 a packet should contain. And also constraint weights for each type of data types D0-D9 in packet.

3) Factory create data rate scheduler class

4) Virtual task body(); // Are below steps looking OK or I am missing something ??

// How do I make sure that packet class random variables are randomized() and proper constraints are applied.

// raise objection

while (not_done) // flag to indicate that keep going till all data type generation is done.

`uvm_create (req);

// 1** do checks here that ipg delay has been met,

// 2 ** also check that there are enough data items in the data queues

// wait here till 1 and 2 ** are not met

for(int i=0; I <8; i++) begin

packet.add_one_data(D0-D8);

end

`uvm_send(req);

end// while

// drop objection

----------------------------------------------

Please provide any comments that you might have regarding the logic

Does above logic ensures that each random variable declared in all classes above will be randomized and proper constraints applied to classes ??

thanks a ton for your help.

Share this post


Link to post
Share on other sites

Hi, I am glad I could help. Below are a my comments on your questions.

Thanks a ton, Whiteriver for your prompt reply. Thanks.

After a daylong thinking, I have come up with following logic.

Please provide your feedback and let me know if I am thinking right, anything that I might be missing.

Also I do have some doubts about the code. I have asked Qs in RED along with my thinking process.

/******** C1 -- data classes ***********/

1) Consists of all the constraints of what contents each data type D0-D8 should contain, and weight distribution given to each data type. Also consists of covergroups.

2) Base class derived from uvm_sequence_item;

----------------------------------------------

/******** C2 - data rate scheduler class ******/

1) This class should be derived from where ???? uvm_sequence_item ??

Should I derive this class from uvm_sequence_item, even though it is not a data type ??

So far I didn't need to create two classes for preparing the data to send, but 'there is always more than one way of doing it'. The uvm_sequence_item should be used by a sequencer, so what you can do is to nest sequences in a sequence run. Look for nested sequences in the documentation.

2) Factory create 9 queues for each of data types D0-D8

Using factory create method, is this right way ??

I guess the factory is good to use here, since the packets derive from the same base class that in turn is derived from uvm_sequence_item. But then, only one queue is simpler to manage if you want to send when 8 packets are ready. the queue would be of the base class type, this is SystemVerilog polymorphism.

3) Implements rate scheduling logic along with constraints to generate data types based on user defined values and pushes them to their respective queue.

4) Also implements logic on extracting back data types from their respective queues.

5) In post_configure phase enable rate_schedular, call randomize (), so that it randomizes the data items and constraint are applied. At this point it will start generating data types.

What should I do so that every time data items are generated they are randomized and proper constraints are applied. Would single call to randomize() work ??

usually I don't call randomize for the packet (it is implied in the uvm_do or uvm_do_with). And yes, the class constrains will apply on every randomization call.

-------------------------------------------

/******** C3 - packet class *************/

1) Class packet extends uvm_sequence_item;

2) Factory create array of type data class of size 8, to fit in 8 consecutive data types in packet

3) Consists of random flags for different types of packet corruption

4) Constraints and cover groups of the order of how data types D0-D8 should fit in packet.

5) Function to add data type to packet “add_one_dataâ€

This I think could be a uvm_sequence. In my view, C1 and C2 can be grouped in one class named 'packet' and then this C3 class is a sequence that orders it to the protocol you are using. On the other side, if the sequencer and driver need the whole 8 packets at once, then C3 should be derived from uvm_sequence_item, as you did.

-------------------------------------------

/********** C4 – sequence class **************/

`include C1, C2, C3 // include all classes: data, data scheduler, packet classes

1) Class packet_sequence extends uvm_sequence # (packet);

2) Include random variables and constraints to specify how many data types 0-8 a packet should contain. And also constraint weights for each type of data types D0-D9 in packet.

3) Factory create data rate scheduler class

4) Virtual task body(); // Are below steps looking OK or I am missing something ??

// How do I make sure that packet class random variables are randomized() and proper constraints are applied.

// raise objection

while (not_done) // flag to indicate that keep going till all data type generation is done.

`uvm_create (req);

// 1** do checks here that ipg delay has been met,

// 2 ** also check that there are enough data items in the data queues

// wait here till 1 and 2 ** are not met

for(int i=0; I <8; i++) begin

packet.add_one_data(D0-D8);

end

`uvm_send(req);

end// while

// drop objection

That makes sense for me. But make sure that the packet is randomized in the 'add_one_data' function, because you are not calling any randomization function from here.

----------------------------------------------

Please provide any comments that you might have regarding the logic

Does above logic ensures that each random variable declared in all classes above will be randomized and proper constraints applied to classes ??

thanks a ton for your help.

It seems the randomization will be called with proper constrains in your code.

Share this post


Link to post
Share on other sites

Hi Guys,

I think you may be overthinking things a bit (although it is possible I'm underthinking ;-)).

If your scheme in VMM was to aggregate data types into a "packet" and then send those to a channel (to be picked up later by the driver), then it would still be the case that your driver would be sitting there waiting for something to appear in the channel. You have two choices:

1 - Have the driver do a "get" from the channel, in which case it will block until something appears, or

2 - Have the driver do a "try_get" from the channel, in which case it will return if there's nothing there

Choice 2 has the advantage of allowing the driver to interact with the bus to do a "null" cycle if there was no packet there. If this is not a requirement, then I'd stick with choice 1 for simplicity.

In UVM, you could have a sequence that interacts with your scheduler to assemble the packet in exactly the same way you're used to. Once the packet is assembled, you could do your start_item/finish_item to send it to the driver. In the driver, choice 1 above would be implemented by having the driver call get_next_item(). Choice 2 would use try_next_item().

In reality, you're doing sequence layering. Your rate scheduler would be a sequence layered on top of your packet sequence. The scheduler sequence generates your data types. The packet sequence gets those data types and assembles them into your packet and sends them to the driver.

Let me know if this makes sense. I can point you to plenty of additional information if you'd like.

Good luck,

-Tom

Share this post


Link to post
Share on other sites

hello Tfitz,

Thanks a lot for your feedback.

Actually, i was not aware of sequence layering. I thought there can be multiple sequences running in parallel or in sequence and there can be library of sequences.

I am re-iterating my requirements here at a very top level and keeping it simple.

1) Data class to form data items

2) data schedular to build 9 queues of different data items and depending on the rate specified by user for each indiviual data type.

3) packet class defining packet structure.

4) packet formatter, forming packets from 9 queues of data types in item 2 above and sending the WHOLE packet to driver.

So from UVM from what i know so far, i thought of having.

1) data as sequence item

2) data scheduler as sequence item

3) packet as sequence item

4) embedding packet formatter logic inside sequence item class, which will form the packet and have all raise and drop objections stuff. and also sent to drive with `uvm_send

Now if i take CHANNEL as in VMM, then the equivalent of UVM i was not able to think.

Here was problem i was facing.

1) data as sequence item, data scheduler as sequence item.

2) packet as sequence item.

Now the packet has to go to driver, so in sequence class i would have:

class packet_sequence extends uvm_sequence #(packet)

but then i was not able to think, where would be the packet formatter logic, which will form the packet and put it in a channel

Where would this channel be ? and how can a packet_sequence class extract the packet from this channel and sent it to the driver.

Those were the things not clear to me and hence i thought on the lines that i listed in post before.

As you suggested that, there could be sequence layering. Please expain a bit on how it would fit in my code and yes please point me to the info.

At learning stage any information is helpful.

thanks a lot, appreciate your time.

Share this post


Link to post
Share on other sites

hi Whiteriver,

Thanks a lot for your feedback.

I am really thankful to you for your time in going through my big big post and answering all my Qs.

I was of great help.

thanks.

Share this post


Link to post
Share on other sites

Actually, i was not aware of sequence layering. I thought there can be multiple sequences running in parallel or in sequence and there can be library of sequences.

Yes, sequences may be run in parallel or in series. On any given sequencer, parallel sequences will be arbitrated by the sequencer so that only one will provide a sequence_item to the driver when asked. If you have multiple sequencers, as for a layering, then each sequencer can be running a sequence. These two sequences can communicate with each other.

I'll answer your questions below, but at this point it's probably best if you visit the Verification Academy and take a look at the "Layered Sequences" unit in the "Advanced UVM" module.

I am re-iterating my requirements here at a very top level and keeping it simple.

1) Data class to form data items

These would be extended from uvm_sequence_item.

2) data scheduler to build 9 queues of different data items and depending on the rate specified by user for each indiviual data type.

The data scheduler would be the top-level sequence. It should be extended from uvm_sequence and this will be what gets explicitly started from your test.

3) packet class defining packet structure.

The packet class will also be extended from uvm_sequence_item. This is the item type that will be passed down to your driver. So, at the agent level, the driver and sequencer will be parameterized using the packet class item.

4) packet formatter, forming packets from 9 queues of data types in item 2 above and sending the WHOLE packet to driver.

The packet formatter would be a uvm_sequence that runs on the agent sequencer and passes packet objects down to the driver.

So from UVM from what i know so far, i thought of having.

1) data as sequence item

2) data scheduler as sequence item

3) packet as sequence item

4) embedding packet formatter logic inside sequence item class, which will form the packet and have all raise and drop objections stuff. and also sent to drive with `uvm_send

See above. In general, you should think of sequence_items as the objects being passed from sequence to driver (or, in a layering as in this case, also between a higher-level sequence and a lower-level sequence). You should keep the raising and dropping of objections to your test:

task run_phase(uvm_phase phase);
 ...
 phase.raise_objection(this, "Starting sequence");
 data_scheduler_sequence.start(top_sequencer);
 phase.drop_objection(this, "Sequence completed");
 ...
endtask

Now if i take CHANNEL as in VMM, then the equivalent of UVM i was not able to think.

Here was problem i was facing.

1) data as sequence item, data scheduler as sequence item.

See above. The data scheduler is a sequence, not a sequence_item.

2) packet as sequence item.

Now the packet has to go to driver, so in sequence class i would have:

class packet_sequence extends uvm_sequence #(packet)

but then i was not able to think, where would be the packet formatter logic, which will form the packet and put it in a channel

Where would this channel be ? and how can a packet_sequence class extract the packet from this channel and sent it to the driver.

You don't actually need a channel. The handshaking is handled automatically via the start_item()/finish_item() in the sequence and the get_next_item() in the driver. In the layering, your packet_formatter sequence (that sends the packet to the driver) serves as what we call a translation sequence. It will actually have to get the data item(s) from the data_scheduler sequence and translate those data items into the packet that it then sends down to the driver. Note that from the data_scheduler's point of view, it's sending data items to what looks like a driver (but is in reality the packet_formatter sequence).

As you suggested that, there could be sequence layering. Please expain a bit on how it would fit in my code and yes please point me to the info.

At learning stage any information is helpful.

I hope I've answered your questions above. Please see the above links to Verification Academy as well.

thanks a lot, appreciate your time.

You're welcome.

Good luck,

-Tom

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0