Data comparison using queues

I’m trying to use queues to populate data and use the data items in queue for comparison. I define a struct which stores the data elements of an item in the queue as follows:

typedef struct {bit[31:0] addr, bit[3:0] id, bit[63:0] data; bit flag} packet_t;

packet_t q1 [$];

I want to populate the addr everytime a new addr comes in, like:

if (intf.a && intf.b)begin
q1.push_front.addr = intf.address;
q1.push_front.id = intf.id;
end

I would like to store the addr and id in the same item (index) of the queue.
(On the next cycle, if intf.a and intf.b evaluate to True, I want to store the id and addr as the second queue item)

Will the above code achieve the intent?
Are there examples of using struct as data type in queues and manipulating them?

When data arrives(along with data id), I plan to use the “find_first with” to find the queue item that matches with the id to store the data into.

Please let me know your inputs.

Thanks!

In reply to Ramyas:

7.10 Queues
A queue is a variable-size, ordered collection of homogeneous elements.

Thus, every push would give you a different index. The following code demos the assembly of the elements of a struct into a variable, then pushing that variable. This compiles OK.
BTW, your original struct def had errors.

module qtest;
	typedef struct {bit[31:0] addr; bit[3:0] id; bit[63:0] data; bit flag;} packet_t;
	packet_t q1 [$], pkt;
	

	//I want to populate the addr everytime a new addr comes in, like:
    initial begin 
    	pkt.addr=5; 
    	pkt.id=2;
    	pkt.data=90;
    	pkt.flag=0;
	q1.push_front(pkt); 
     end

	/* I would like to store the addr and id in the same item (index) of the queue. 
		(On the next cycle, if intf.a and intf.b evaluate to True, I want to store the id and addr as the second queue item)

		Will the above code achieve the intent?
		Are there examples of using struct as data type in queues and manipulating them?

		When data arrives(along with data id), I plan to use the "find_first with" to find the queue item that matches with the id to store the data into.
    */
endmodule

Ben Cohen
http://www.systemverilog.us/

  • SystemVerilog Assertions Handbook 3rd Edition, 2013 ISBN 878-0-9705394-3-6
  • A Pragmatic Approach to VMM Adoption 2006 ISBN 0-9705394-9-5
  • Using PSL/SUGAR for Formal and Dynamic Verification 2nd Edition, 2004, ISBN 0-9705394-6-0
  • Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn 0-9705394-2-8
  • Component Design by Example ", 2001 ISBN 0-9705394-0-1
  • VHDL Coding Styles and Methodologies, 2nd Edition, 1999 ISBN 0-7923-8474-1
  • VHDL Answers to Frequently Asked Questions, 2nd Edition ISBN 0-7923-8115

This will work except you must push one complete item at a time onto the queue. You can’t push the address, then the id separately. You can use an assignment pattern to create an anonymous packet_t, meaning you don’t have to create a temporary variable and push it onto the queue.

q1.push_front( packet_t'{ addr: intf.address, id: intf.id } );

However, you should only use a queue if you need to maintain the ordering that the addresses come in to you. Searching through s queue can become quite time consuming as the list grows. Otherwise, use an associative array and use an index key that you will use to lookup the most; either addr or id in your example.

packet_t a1 [bit[3:0]]; 

a1[intf.id] = packet_t'{ addr: intf.address, id: intf.id };

In reply to dave_59:

Thank you Dave and Ben .

Using associative was and still is my preference. But, the problem arises when the next set of address arrives with the same id as the previous one (if I were to use address as the key instead of id, there are scenarios where there can be two consecutive addresses of the same value.) I need to group the address/data on both the inputs and outputs of the DUT (the DUT will re-order the address/id that is being input to it) and compare them when the last beat of data is received on either ends(for reads and writes). Is there a way the grouping can be done using associative arrays? Please let me know

In reply to Ramyas:

Ramyas,

You may need to provide some actual examples to explain your requirements. What defines a “set” of addresses? What is a “beat” of data?

You say that one set of addresses could have the same ID as the next. In your original post, you said you were going to use find_first() to match an ID. But since you were using push_front, that would imply there is an ordering and you would get only the newest entry to the queue with that ID.

There might not be enough time to explain in this forum, so let me give you a few other suggestions that you can ponder.

An associative array can have more than one key with multiple dimensions.


packet_t a1[key1_type][key2_type];

The ordering of the the keyN_types in the declaration is important if you plan to look up things without all the keys available. a1[value1] returns an associative array of all key2 elements whose key1 value matches value1. But there is no way to do something like a[***][value2] to get associative array of all key1 elements whose key2 value matches value2 without iterating over all key1 values.

It’s also possible to have a key with a complex structure.

typedef struct {bit[31:0] addr, bit[3:0] id} key_t;

packet_t a1[key_t];

a1['{intf.addr,intf.id}] = '{ addr: intf.address, id: intf.id };

BTW, there is no need to have a field be in two places, both in the key and inside the packet data struct unless it makes it easier for copying and comparing.