Yes. UVM has a class-based dynamic queue that can be allocated on demand, passed and stored by reference. Eventhough
uvm_queue is a parameterized class extended from
uvm_object, it is not registered with the factory and hence invocation of
new() function is the correct way to create a queue object.
Also, UVM provides a global singleton queue instance by the name
m_global_queue which can be retrieved via
get_global_queue() method. This allows items to be shared amongst components throughout the verification environment.
class uvm_queue #(type T = int) extends uvm_object; ... typedef uvm_queue #(T) this_type; static local this_type m_global_queue; protected T queue[$]; static function this_type get_global_queue(); ... endclass
In the following example, we'll see how to use a queue in real UVM code.
class my_data extends uvm_sequence_item; // my custom data object endclass class my_test extends uvm_test; ... uvm_queue #(my_data) my_q; virtual task main_phase (uvm_phase phase); // Create a new object and assign to handle my_q my_q = new ("my_q"); my_data tmp = my_data::type_id::create ("tmp"); my_q.push_back (tmp); endtask endclass
Here are a few examples on how to use some of the popular methods of the
my_data obj = my_q.get (i); // where i can be an integer 0 to my_q.size() qsize = my_q.size (); // Get number of elements in the queue obj = get_global (5); // Get the item at index 5 from the global queue my_q = get_global_queue(); // Get handle to the global queue my_q.insert (4, obj); // Insert obj at index 4 my_q.delete (); // Delete all elements in the queue my_q.delete (2); // Delete element at index 2 obj = my_q.pop_front () // Pop the item at the front of the queue obj = my_q.pop_back () // Pop the item at the back of the queue my_q.push_back (obj); // Push the object to the back of the queue my_q.push_front (obj); // Push the object to the front of the queue