When we start multiple sequences in testcase or virtual sequence, all these sequences are getting stored inside the sequencer in queue. So we can assign the priority when we want to prioritize particular sequence over other sequences.
UVM Sequencer has six arbitration modes:
UVM_SEQ_ARB_FIFO
Here sequencer grants sequences in FIFO order regardless of the mentioned priority.
So in blow order driver will get the packet:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_SEQ_ARB_RANDOM
Here, we will do below modification in child sequence:
In this case, sequencer randomly grants the sequences without bothering about the priority.
So the output we got:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_SEQ_ARB_STRICT_FIFO
Here, we will do below modification in child sequence:
And in virtual sequence:
seq[1].start(p_sequencer.my_seqr, .this_priority(50));
seq[2].start(p_sequencer.my_seqr, .this_priority(150));
seq[3].start(p_sequencer.my_seqr, .this_priority(150));
In this case, sequencer will strictly follow the priority of each and every sequence inside the FIFO.
So the output would be:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
Here, seq[2] and [3] has the same priority but as it is a strict FIFO, it will grant the closest one.
UVM_SEQ_ARB_STRICT_RANDOM
Here, we will do below modification in child sequence:
And in virtual sequence:
seq[1].start(p_sequencer.my_seqr, .this_priority(50));
seq[2].start(p_sequencer.my_seqr, .this_priority(150));
seq[3].start(p_sequencer.my_seqr, .this_priority(150));
UVM_SEQ_ARB_WEIGHTED
This is bit complicated than other arbitration methods. The idea of this mode is higher priority sequences will get more chance to be granted.
How it works: Summation of all the sequence priorities inside the request queue is happened. (Here, 100 + 50 + (150*3) = 600). Now from 0 to 599 any random number has been chosen. From the front of the FIFO it start summation of the priority number each sequence has, when the summation exceeds the randomly selected number, that sequence is selected.
Let's say, from 0 to 599 randomly selected number is 219. So now from the front of the FIFO it will start adding each sequence's priority. Here it starts with 100 then 150 (100+50) and then 300 (100+50+150). As 300 is bigger than 219, Sequence 3 will be selected. Similar will continue till there's request inside the FIFO.
Here output we got:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 5
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_SEQ_ARB_USER
int lowest_pri;
int lowest_pri_id;
lowest_pri = m_get_seq_item_priority(arb_sequence_q[avail_sequences[0]]);
lowest_pri_id = 0;
for (int i = 1; i < avail_sequences.size(); i++)
begin
if (m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) < lowest_pri)
begin
lowest_pri = m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]);
lowest_pri_id = i;
end
end
UVM Sequencer has six arbitration modes:
- UVM_SEQ_ARB_FIFO (This is default mode)
- UVM_SEQ_ARB_RANDOM
- UVM_SEQ_ARB_STRICT FIFO
- UVM_SEQ_ARB_STRITCT_RANDOM
- UVM_SEQ_ARB_WEIGHTED
- UVM_SEQ_ARB_USER
Code:
---------------------------------------------------------------------
class my_seq extends uvm_sequence#(my_packet);
...
virtual task body();
m_sequencer.set_arbitration(SEQ_ARB_FIFO);
m_sequencer.set_arbitration(SEQ_ARB_FIFO);
pkt = my_packet::type_id::create("pkt");
start_item(pkt);
pkt.randomize() with {pkt.data == id;};
finish_item(pkt);
endtask: body
start_item(pkt);
pkt.randomize() with {pkt.data == id;};
finish_item(pkt);
endtask: body
endclass: my_seq
---------------------------------------------------------------------
---------------------------------------------------------------------
class my_vir_seq extends uvm_sequence;
my_seq seq[];
...
virtual task body();
seq = new[4];
seq = new[4];
for (int i = 0; i < seq.size; i++)
begin
seq[i] = my_seq::type_id::create($sformatf("seq[%0d]", i));
seq[i].id = i + 1;
end
begin
seq[i] = my_seq::type_id::create($sformatf("seq[%0d]", i));
seq[i].id = i + 1;
end
fork
seq[0].start(p_sequencer.my_seqr, .this_priority(100)); // 100 is the default priority
seq[1].start(p_sequencer.my_seqr, .this_priority(50));
seq[2].start(p_sequencer.my_seqr, .this_priority(150));
seq[3].start(p_sequencer.my_seqr, .this_priority(49));
join
endtask: body
seq[0].start(p_sequencer.my_seqr, .this_priority(100)); // 100 is the default priority
seq[1].start(p_sequencer.my_seqr, .this_priority(50));
seq[2].start(p_sequencer.my_seqr, .this_priority(150));
seq[3].start(p_sequencer.my_seqr, .this_priority(49));
join
endtask: body
endclass: my_vir_seq
---------------------------------------------------------------------
In above code, we have set the priority inside the child sequence, the reason behind that is all these sequences are going to start on that sequencer and queue of this sequencer is going to fill with the sequences.
UVM_SEQ_ARB_FIFO
Here sequencer grants sequences in FIFO order regardless of the mentioned priority.
So in blow order driver will get the packet:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_SEQ_ARB_RANDOM
Here, we will do below modification in child sequence:
---------------------------------------------------------------------
m_sequencer.set_arbitration(SEQ_ARB_RANDOM);
---------------------------------------------------------------------
In this case, sequencer randomly grants the sequences without bothering about the priority.
So the output we got:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_SEQ_ARB_STRICT_FIFO
Here, we will do below modification in child sequence:
---------------------------------------------------------------------
m_sequencer.set_arbitration(SEQ_ARB_STRICT_FIFO);
---------------------------------------------------------------------
And in virtual sequence:
---------------------------------------------------------------------
seq[0].start(p_sequencer.my_seqr, .this_priority(100));seq[1].start(p_sequencer.my_seqr, .this_priority(50));
seq[2].start(p_sequencer.my_seqr, .this_priority(150));
seq[3].start(p_sequencer.my_seqr, .this_priority(150));
---------------------------------------------------------------------
In this case, sequencer will strictly follow the priority of each and every sequence inside the FIFO.
So the output would be:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
Here, seq[2] and [3] has the same priority but as it is a strict FIFO, it will grant the closest one.
UVM_SEQ_ARB_STRICT_RANDOM
Here, we will do below modification in child sequence:
---------------------------------------------------------------------
m_sequencer.set_arbitration(SEQ_ARB_STRICT_RANDOM);
---------------------------------------------------------------------
And in virtual sequence:
---------------------------------------------------------------------
seq[0].start(p_sequencer.my_seqr, .this_priority(100));seq[1].start(p_sequencer.my_seqr, .this_priority(50));
seq[2].start(p_sequencer.my_seqr, .this_priority(150));
seq[3].start(p_sequencer.my_seqr, .this_priority(150));
seq[4].start(p_sequencer.my_seqr, .this_priority(150));
---------------------------------------------------------------------
In this case, sequencer will strictly follow the priority but when two or more sequences are having the same priority, sequencer will randomly pick the sequences that have the same priority. So the output we got:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 5
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 5
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_SEQ_ARB_WEIGHTED
Here, we have done below modification in child sequence:
---------------------------------------------------------------------
m_sequencer.set_arbitration(SEQ_ARB_WEIGHTED);
---------------------------------------------------------------------
How it works: Summation of all the sequence priorities inside the request queue is happened. (Here, 100 + 50 + (150*3) = 600). Now from 0 to 599 any random number has been chosen. From the front of the FIFO it start summation of the priority number each sequence has, when the summation exceeds the randomly selected number, that sequence is selected.
Let's say, from 0 to 599 randomly selected number is 219. So now from the front of the FIFO it will start adding each sequence's priority. Here it starts with 100 then 150 (100+50) and then 300 (100+50+150). As 300 is bigger than 219, Sequence 3 will be selected. Similar will continue till there's request inside the FIFO.
Here output we got:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 5
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_SEQ_ARB_USER
Here, we have done below modification in child sequence:
---------------------------------------------------------------------
m_sequencer.set_arbitration(SEQ_ARB_USER);
---------------------------------------------------------------------
Here, user can write his/her own logic to select the sequences available in queue. For that user has to define user_priority_arbitration function inside its own sequencer. This function is being called by uvm_sequencer_base only if arbitration type is SEQ_ARB_USER.
In our case, in sequencer file we have added below logic to select the lowest priority sequence first:
---------------------------------------------------------------------
virtual function integer user_priority_arbitration( integer avail_sequences[$] );int lowest_pri;
int lowest_pri_id;
lowest_pri = m_get_seq_item_priority(arb_sequence_q[avail_sequences[0]]);
lowest_pri_id = 0;
for (int i = 1; i < avail_sequences.size(); i++)
begin
if (m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) < lowest_pri)
begin
lowest_pri = m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]);
lowest_pri_id = i;
end
end
return avail_sequences[lowest_pri_id];
endfunction: user_priority_arbitration
endfunction: user_priority_arbitration
---------------------------------------------------------------------
Based on the above code, output we got:
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 2
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 5
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 1
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 3
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 4
UVM_INFO my_driver.sv(15) @ 0: uvm_test_top.env.agent.driver [driver] Received data is 5
No comments:
Post a Comment