Warning: session_start(): Cannot send session cookie - headers already sent by (output started at /home2/aefody/public_html/specman-verification.com/scripts/sb_utility.php:873) in /home2/aefody/public_html/specman-verification.com/index.php on line 11

Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at /home2/aefody/public_html/specman-verification.com/scripts/sb_utility.php:873) in /home2/aefody/public_html/specman-verification.com/index.php on line 11

Warning: strpos(): needle is not a string or an integer in /home2/aefody/public_html/specman-verification.com/index.php on line 35

Warning: strpos(): needle is not a string or an integer in /home2/aefody/public_html/specman-verification.com/index.php on line 47

Warning: strpos(): needle is not a string or an integer in /home2/aefody/public_html/specman-verification.com/index.php on line 59

Warning: strpos(): needle is not a string or an integer in /home2/aefody/public_html/specman-verification.com/index.php on line 71
Tips for HVL and HDL users with special emphasis on Specman-e, SystemVerilog and Questa
Specman Verification
Verification engineer? Verifigen has the right project for you!
Beware of disable fork! 
Thursday, September 4, 2008, 03:54 PM - The verification hood

One of the coolest things about Verilab, apart from the company’s private jet and yacht, is the deep and highly informed email discussions that are constantly taking place. As a blogger this is also an excellent place to steal ideas from. For example, an email sent by my colleague, Gordon Allan, this morning, pointed out a strange behavior of “disable fork”. Turns out that a “disable fork” kills not only the processes that were started by the fork statement just above it, but every process that was started by the current process. If you’re confused by this last sentence, take a look at the following code (compiled and simulated with Questa 6.3):

module top;

   initial begin



      // This process will be killed by the

      // disable fork statement at the bottom.

      // The reason is that a disable fork 

      // statement kills all processes that 

      // were started by the process that excutes it.

      fork

         do begin

            #1;

            $display("1st thread running");

         end while($time<10);

      join_none



      fork

         // This process will reach its end

         begin

            #3;

            $display("2nd thread finished");

         end



         // This process will be terminated

         // because of the disable fork

         // statement as expected.

         begin

            #4;

            $display("3rd thread finished");

         end

      join_any

      disable fork;

   end

endmodule

Output:
1st thread running
1st thread running
2nd thread finished


As can be seen, not only the third process, but also the first process is killed by the "disable fork" statement at the bottom. That's because the first process is a child of the current process as well.

So, how can you apply "disable fork" to one specific fork statement only? One solution is to name your fork, as shown below.

module top;

   initial begin

      fork

         do begin

            #1;

            $display("1st thread running");

         end while($time<10);

      join_none



      // The solution - name the fork so

      // that you can disable it specifically

      fork : a

         begin

            #3;

            $display("2nd thread finished");

         end



         begin

            #4;

            $display("3rd thread finished");

         end

      join_any : a

      disable a;

   end

endmodule

Note, that now you're just disabling the named block, and not using the "disable fork" statement anymore. This solution will work in this case, but as Gordon Allan (thanks again!) rightly points out in his comment below, should be avoided when your code is "reentrant", in other words, whenever there exists a possibility that your code will be used by two different threads simultaneously. For example, an "automatic task" is reentrant, because it is meant to be used by several independent processes at the same time. The problem with disabling a named block in this case, is that it is not "thread-safe" and will therefore affect all the processes that are using that same piece of code. Confused? then just have a look at the simple example below:

module top1;

   initial begin

      fork

         fork_processes(4);

         fork_processes(7);

      join_none



   end 

   task automatic fork_processes(int delay);

      fork : a

         begin

            #delay;

            $display("Thread finished");

         end

      join_any : a

      disable a;

   endtask

endmodule 


Output:
Thread finished

As can be seen, when the disable statement in one of the task calls is reached, both task calls end, and therefore you get only one "Thread ended" message from the thread that ends at time 4. This means that if you're disabling a named block inside reentrant code, then for every practical purpose except writing a blog, your code will not be reentrant anymore.

So, the choice is between pest and cholera: use disable fork, and all sub processes of the same process are gone; use disable named block and your code is not reentrant any more. I guess the only certain advice I could give is to be extremely careful about anything you do when you're using SV's "fine grain process control" (couldn't help a bit of cynicism here)...

For more details about named blocks, and how to disable them see sections 10.8 and 10.9 of the SV standard. For more about disable fork see 11.8


  |  permalink
"We've always been at war with Eastasia" 
Thursday, August 16, 2007, 02:01 PM - The verification hood
We all thought Mentor and Cadence were bitter rivals, but that was all just a brilliant trick to outsmart Synopsys and put it offguard. Read the latest dispatch on the subject from the Ministry of Truth...

When you're done you might feel like shooting the breeze and discussing the winners and losers from this deal. Here's what went through my head in the first few seconds:

Mentor : the big winner. They made a very smart move with their open source AVM and now they are picking up the fruits. The AVM is a good start, but is not yet mature enough to convince customers to migrate. With Cadence's stamp on it, it will look much more tempting.

Cadence : are risking their Specman market share, for a better position in the SystemVerilog race.

Me : Not too bad as well. With Cadence inside I'm sure OVM is going to become more Specman-like then the AVM, which is good, because I do believe that when it comes to methodology, nobody has managed to do as good as Specman so far. Hopefully, with joint forces, they will...

Feel free to add your unqualified remarks and wild guesses to mine. It will make a good laugh one year from now...
  |  permalink
SV enumerated types riddle 
Thursday, August 9, 2007, 12:56 PM - The verification hood
The SV standardization committee awards 50 bucks to anyone who can predict the output of the code snippet below:


typedef enum int {c=2, b=1, a=0} upside_down_t;



module x;

   initial begin

      upside_down_t upside_down;



//$display("upside_down.first() = %d",upside_down.first());

//$display("upside_down.last() = %d",upside_down.last());

      

      for (upside_down = upside_down.first(); upside_down <= upside_down.last(); upside_down = upside_down.next())

        $display(upside_down.name());

   end

endmodule


output :

No, I haven't forgot it. This code will print nothing. Why? basically because the highest value of the enumerated type is defined first. Confused? uncomment the $display statements and things will become clearer:

output :

upside_down.first() = 2
upside_down.last() = 0

So, here's what happens: The first value of the enumerated type is not the one with the lowest integer value, but the leftmost one in the definition. Accordingly, the last value is the rightmost in the definition, and not the one with the highest integer value. The following expression, calculated according to the integer values, is therefore false:

upside_down.first() <= upside_down.last()

und the loop is not executed...

And of course the standardization committee gets to keep its 50 bucks :-)


  |  permalink

Back Next