How to end all outstanding objections in OVM - system-verilog

I am in run phase and lets say I have raised 20 objections. I want to end all these 20 objections already raised and raise 20 new objections in the same phase without jumping to the next phase. Can someone please suggest how to achieve this?

Here is first method(you don't know how many objections were raised):
phase.raise_objection(this);
phase.raise_objection(this);
//your code here
m_phase.drop_objection(this, "", m_phase.get_objection_count(this));
Here is same method (assuming you know how many objections were raised):
phase.raise_objection(this, "raise 3 objections", 3);
//your code here
m_phase.drop_objection(this, "drop 3 objections", 3);
end
Less clever method, but worth mentioning:
`uvm_info(get_type_name(), $sformatf("Dropping all objections now"), UVM_MEDIUM)
for (int i=0 ; m_phase.get_objection_count(this) > 0; i++) begin
`uvm_info(get_type_name(), $sformatf("Dropping objection #%d", i), UVM_MEDIUM)
m_phase.drop_objection(this);
end
You can find more information about uvm_phase class here:
https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.2/html/files/base/uvm_phase-svh.html
I also coded these examples for you to try here:
https://www.edaplayground.com/x/2KLd

Related

randcase weight behaviour unexpected

class test1;
function test_randcase();
for (int idx=0; idx < 10; idx++) begin
randcase
50: begin
$display("displaying from first cases");
end
50: begin
$display("displaying from second case");
end
endcase
end
endfunction
endclass
program main;
initial begin
test1 t1=new();
t1.test_randcase();
end
endprogram
Since each case is equally weighed here (50/100=0.5) so the expectation is that I would see each display 5 times in total. However, I see "first case" print 6 times and "second case" print 4 times. If this is the behavior of randcase, then how would I achieve my intention of equal weight? I used vcs compiler for this execution.
output:
displaying from second case
displaying from first cases
displaying from first cases
displaying from first cases
displaying from first cases
displaying from second case
displaying from first cases
displaying from second case
displaying from second case
displaying from first cases
Looking at this problem another way, suppose you had to choose a completely random 10-bit number where each bit has a 50% chance of being 0 or 1. There are 1024 possible numbers with a 1/1024 chance of having 10 1's and a 1/1024 chance of having 10 0's. And the odds of choosing a number with exactly 5 1's and 5 0's is around 25%. If you run more iterations, your randcase distribution would approach 0.50, but the odds of getting an exact 0.5 distribution diminish.
If your requirement is getting an exact distribution, you need to know upfront how many iterations you plan to have. There are several approaches you could take, one of which I can show you
class test1;
enum {FIRST, SECOND} itor[10];
function new;
itor[0:4] = '{5{FIRST}};
itor[5:9] = '{5{SECOND}};
endfunction
function void test_randcase();
itor.shuffle();
foreach(itor[i]) begin
case(itor[i])
FIRST: begin
$display("displaying from first cases");
end
SECOND: begin
$display("displaying from second case");
end
endcase
end
endfunction
endclass
module main;
test1 t1=new();
initial repeat(10)begin
$display("---");
t1.test_randcase();
end
endmodule
Other ways are shown in my paper from DVCon 2020, SystemVerilog Constraints: Appreciating What You Forgot in School to Get Better Results

Same sequence to multiple sequencers in UVM

I have a DUT with 2 Interfaces of the same type. I have created 2 agents to drive the two interfaces. My idea is to drive the same signals on the interface ports to test a specific scenario. Hence, I thought of creating a sequence and driving it to the two sequencers of the agents. But I get an error. The code is something as follows:
my_sequencer m_seqr[2];
my_sequence m_seq;
for(int i=0; i<2; i++) begin
fork
int idx = i;
m_seq.start(p_sequencer.m_seqr[i];
join_none
end
I haven't shown the complete code for keeping the post short. I think my declarations and initializations are correct because I have a similar test with 2 sequences feeding into 2 sequencers working correctly.
My question is how can I achieve my objective of driving the same sequence into 2 or more sequencers?
Error is as follows(Haven't added the complete line of error):
uvm_test_top.m_env.m_my_agent_env.m_my_agent[1].m_seqr##m_in_seq%0d[SEQ_NOT_DONE] Sequuence .... already started
You need to construct a new object for each sequence you want to start. Also, you need to reference [idx] not [i].
my_sequencer m_seqr[2];
...
for(int i=0; i<2; i++)
fork
int idx = i;
my_sequence m_seq = my_sequence::type_id::create(...);
m_seq.start(p_sequencer.m_seqr[idx];
join_none

delete queue items inside foreach loop

When we need to delete some items inside a queue, we may easily write code like below:
foreach(queue[i]) begin
if(queue[i].value == 1)
queue.delete(i);
end
But there is bugs in above code when queue[0]==queue[1]==1. Because queue.delete(0) will change all indexes of items inside queue.
So currently I use code as below:
foreach(queue[i]) begin
if(queue[i].value == 1) begin
queue.delete(i);
i--;
end
end
It works, but it looks confusing at first glance.
So my question is:
Are there any better solution for this issue in system verilog?
I believe this should work (I'm unable to test it right now. Make sure order is persevered when you try it out)
queue = queue.find() with ( item.value != 1 );
Another approach would be to find all the indexes that meet your criteria, sort in depending order, then loop through the indexes
int qi[$] = queue.find_index() with ( item.value == 1 );
qi = qi.sort() with ( -item ); // sort highest to lowest
foreach(qi[idx]) queue.delete(qi[idx]);
Refer to IEEE1800-2012 § 7.12 Array manipulation methods for details

Debugging Skip to a step in for loop

Considering debugging through a for loop
The length for this loop is just used for demo purpose
for (int i = 0; i < 10000; i++) {
//do something
//something more
//something more
}
how do i skip to Xth iteration i would want to test : in this case if i want to test what happens when i=567.
is there any way by which i can have eclipse halted precisely at i=567 in this loop ?
I am debugging over many for loops which run over varying large lengths.
Switch to Debug Perspective.Go to Break point view. Select the break point and enable hit count and enter hit count as 567.

Which costs more while looping; assignment or an if-statement?

Consider the following 2 scenarios:
boolean b = false;
int i = 0;
while(i++ < 5) {
b = true;
}
OR
boolean b = false;
int i = 0;
while(i++ < 5) {
if(!b) {
b = true;
}
}
Which is more "costly" to do? If the answer depends on used language/compiler, please provide. My main programming language is Java.
Please do not ask questions like why would I want to do either.. They're just barebone examples that point out the relevant: should a variable be set the same value in a loop over and over again or should it be tested on every loop that it holds a value needed to change?
Please do not forget the rules of Optimization Club.
The first rule of Optimization Club is, you do not Optimize.
The second rule of Optimization Club is, you do not Optimize without measuring.
If your app is running faster than the underlying transport protocol, the optimization is over.
One factor at a time.
No marketroids, no marketroid schedules.
Testing will go on as long as it has to.
If this is your first night at Optimization Club, you have to write a test case.
It seems that you have broken rule 2. You have no measurement. If you really want to know, you'll answer the question yourself by setting up a test that runs scenario A against scenario B and finds the answer. There are so many differences between different environments, we can't answer.
Have you tested this? Working on a Linux system, I put your first example in a file called LoopTestNoIf.java and your second in a file called LoopTestWithIf.java, wrapped a main function and class around each of them, compiled, and then ran with this bash script:
#!/bin/bash
function run_test {
iter=0
while [ $iter -lt 100 ]
do
java $1
let iter=iter+1
done
}
time run_test LoopTestNoIf
time run_test LoopTestWithIf
The results were:
real 0m10.358s
user 0m4.349s
sys 0m1.159s
real 0m10.339s
user 0m4.299s
sys 0m1.178s
Showing that having the if makes it slight faster on my system.
Are you trying to find out if doing the assignment each loop is faster in total run time than doing a check each loop and only assigning once on satisfaction of the test condition?
In the above example I would guess that the first is faster. You perform 5 assignments. In the latter you perform 5 test and then an assignment.
But you'll need to up the iteration count and throw in some stopwatch timers to know for sure.
Actually, this is the question I was interested in… (I hoped that I’ll find the answer somewhere to avoid own testing. Well, I didn’t…)
To be sure that your (mine) test is valid, you (I) have to do enough iterations to get enough data. Each iteration must be “long” enough (I mean the time scale) to show the true difference. I’ve found out that even one billion iterations are not enough to fit to time interval that would be long enough… So I wrote this test:
for (int k = 0; k < 1000; ++k)
{
{
long stopwatch = System.nanoTime();
boolean b = false;
int i = 0, j = 0;
while (i++ < 1000000)
while (j++ < 1000000)
{
int a = i * j; // to slow down a bit
b = true;
a /= 2; // to slow down a bit more
}
long time = System.nanoTime() - stopwatch;
System.out.println("\\tasgn\t" + time);
}
{
long stopwatch = System.nanoTime();
boolean b = false;
int i = 0, j = 0;
while (i++ < 1000000)
while (j++ < 1000000)
{
int a = i * j; // the same thing as above
if (!b)
{
b = true;
}
a /= 2;
}
long time = System.nanoTime() - stopwatch;
System.out.println("\\tif\t" + time);
}
}
I ran the test three times storing the data in Excel, then I swapped the first (‘asgn’) and second (‘if’) case and ran it three times again… And the result? Four times “won” the ‘if’ case and two times the ‘asgn’ appeared to be the better case. This shows how sensitive the execution might be. But in general, I hope that this has also proven that the ‘if’ case is better choice.
Thanks, anyway…
Any compiler (except, perhaps, in debug) will optimize both these statements to
bool b = true;
But generally, relative speed of assignment and branch depend on processor architecture, and not on compiler. A modern, super-scalar processor perform horribly on branches. A simple micro-controller uses roughly the same number of cycles per any instruction.
Relative to your barebones example (and perhaps your real application):
boolean b = false;
// .. other stuff, might change b
int i = 0;
// .. other stuff, might change i
b |= i < 5;
while(i++ < 5) {
// .. stuff with i, possibly stuff with b, but no assignment to b
}
problem solved?
But really - it's going to be a question of the cost of your test (generally more than just if (boolean)) and the cost of your assignment (generally more than just primitive = x). If the test/assignment is expensive or your loop is long enough or you have high enough performance demands, you might want to break it into two parts - but all of those criteria require that you test how things perform. Of course, if your requirements are more demanding (say, b can flip back and forth), you might require a more complex solution.