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!
Parsing Verilog using Perl (out of boredom) 
Saturday, September 26, 2009, 06:31 AM - Hardcore verification
I've always suspected that boredom, not money, power, sex or anything else, is what makes the world go around and after 3 weeks of unemployment, now finally behind me, I am at last able to confirm this suspicion. In search of something meaningful to do with my time between the beach, the Israeli version of Survivor, and some occasional meetings with potential employers, I decided to pursue an idea I had some time ago, and try to implement it myself. This took me into an unexpected direction of trying to figure out what's the best way of parsing Verilog files. It is hard to say at this stage where my idea will end up, but as a by-product I got some short useful insights and some real code for anyone who intends to use Perl to look into the entrails of a Verilog file...

Starting with google, a simple search of "perl verilog parser" will immediately take you to a package called Verilog::Parser, and another package called v2html. Using these ready-made packages is an easy way to go, but you have to be aware that both of them will hide out a lot of information that you might want to have. Verilog::Parser, for example, breaks a Verilog file into atoms such as keywords, tokens, and numbers and gives you a callback for each. However, if you want to look for something bigger, say, a complete "always" block, you will find yourself re-parsing these atoms into blocks, which is not an easy task. Since my idea required a more high-level point of view, I decided to look for something else.

The next step, therefore, was to dump Verilog::Parser and v2html, and just look at parsing files with Perl. I was assuming that Perl has something generic to offer here, since almost every second programmer, uses Perl exactly for this kind of task. And in fact, Perl does have a very cool and well documented package called Parse::RecDescent, which will parse any file according to any BNF grammar you provide, and enable you to preform custom things for any production it sees on its way. Verilog's BNF can be found here, and in a version that can be easily converted into what Perl's RecDescent would eat, right here. This last link leads to a page under ANTLR's website, and I'll go back to talk about ANTLR in a second.

After adapting the grammar to Perl and installing RecDescent, I was ready to go, and although I still have some difficulties implementing my idea, they're much smaller compared to the ones I had to deal with before...If you think this might be useful for you as well, you can download my Verilog grammer for Perl's RecDescent, and a small example, right here.

As mentioned above I adapted the Perl RecDescent Verilog grammer from a grammer I found on ANTLR's site. This, of course, made me curious about what ANTLR was, and I soon found out it was a very cool free IDE for debugging grammar's and building compilers. For example, it can give you a graphical representation of any grammer you load into it, which can be very helpful when you're trying to figure out how a rule is broken down into individual productions all the way to the individual identifiers. It also has an active user community which had helped me patiently with some stupid questions I had. It is worth trying out...

  |  permalink
No comments! 
Monday, August 17, 2009, 11:04 AM - Hardcore verification
Due to an annoying spam comments attack I've decided to disable comments for a while. Please feel free to contact me directly with anything you would like to say at avidan_e at yahoo dot com.
  |  permalink
Do you believe in life after „when“ inheritance? 
Saturday, August 1, 2009, 10:13 AM - Hardcore verification
e „when“ inheritance has something in common with the internet, the cell-phone, the TV, the reality show and all of these other great inventions: Everybody that was born into the world after they were invented has a very hard time imagining life without it. This disbelief persists even in the face of overwhelming proofs that life can and do exist without these inventions, such as the shocking personal testimonies of people who used to have books in their living room instead of a HD flat screen. Going back to the verification world, people who have used “when” are often convinced that it is impossible to really verify a DUT without this feature, no matter how many one spin tape-outs to the contrary you present them with.

As one of the few people who have gone back in time from a world with “when” to a world without it, I think I have quite a comprehensive view with regards to the needs and requirements that “when” inheritance fulfils, the alternatives to “when” inheritance that SV/OVM has to offer, and the shortcomings of these alternatives. For the sake of my impatient readers, I’ll start with the bottom line: working with a language that doesn’t support “when”, will make your code uglier, and your debugging harder. However, it is definitely not the end of the world.

“when” inheritance is very strong where transactions of different types take place on a single channel completely at random. This somewhat lame description can be resumed in one word: packets. Packet traffic is often made of several types of packets that can appear on a single channel completely at random. When you’re dealing with this kind of traffic, using “when” inheritance will make your code cleaner and easier to debug.

In order to understand why, let us have a look at the two common solutions to generating such packet traffic in SV/OVM. In the first solution, often referred to as “the factory” solution, you would have a different class for each packet type. To generate the packet traffic, you have to go in two stages: First you randomly select the type of the packet you would like to generate next, then you generate an instance of the corresponding class. The code at the end of this entry (which can be used by OVM newbies also as a complete sequence example) demonstrates this solution.

At the height of the e-SV wars, some years ago, this solution was strongly promoted as a “when” replacement. Personally, I don’t like it at all, mainly because of (A) the two step randomization proecess, which limits the use of bidirectional constraints and (B) the fact that the type of the packet, which in my eyes is a property of the packet, is actually moved out of the packet to the factory that generates it (in the case of my example, the factory is located in the sequence). If you would like to constrain all packets to be of a certain type, you have to add a constraint to the factory, not to the packet as you would do in the case of “when”. This means that some of the packet properties are constrained through the packet object itself, while others are constrained through the factory. Ugly. It was also said at the time that this solution might lead to a “class explosion” if you have more then one “when” determinant. From my experience, this doesn’t happen too often in real life projects, so this objection belongs more in the theoretical realm.

If you would like to keep all the packet properties in one single packet class, like me, and still be able to generate different kinds of packets, at a distribution that can be easily constrained from the test by the user, the easiest solution is simply to have a packet class which is the aggregation of all the subtypes. This means that the packet class has all the fields of all the subtypes, but for a specific subtype, only some of these fields are actually valid/used. Obviously, the downside of this approach is that you have many garbage fields in your class, and this might make debugging more complex. When you open your packet in a watch window, you will have to search a bit for the fields that are actually relevant for you. However, this pain can be somewhat reduced by providing type-specific print functions.

So, as said above, verification without “when” is possible, at the price of some ugliness of code, or some extra effort in debugging and if this takes several thousand dollars off your license fees, it is worth considering. What prevents many e people from seeing this simple truth is, I believe the fact that “when” inheritance is very often used at places where it is not really required. Take for example the vr_ad register package: is it really required to define each register as a “when” subtype, or could they also be defined as normal derived classes of a register base class? In my opinion, “when” has little added value here. It is very rare that you just choose to read or write a random register, and if you know which register you’re reading or writing upfront, why don’t you just instantiate the register class you want? In this case, instantiating a specific class and randomizing it means almost no additional pain. Where the type and the transaction are completely random, “when” is a big help. Where the type is not random, and the transaction is, you can do just as well with normal OO.

You can read some more on "when" inheritance in SV here

Factory example:

package packet_pkg;



import ovm_pkg::*;

`include "ovm_macros.svh"



typedef enum {A, B} packet_type_t;



class packet_base extends ovm_sequence_item;

   `ovm_object_utils(packet_base);



   function new(string name = "");     

      super.new(name);     

   endfunction

endclass



class packet_A extends packet_base;

   

   rand int a;



   `ovm_object_utils_begin(packet_A);

   `ovm_field_int(a, OVM_ALL_ON)

   `ovm_object_utils_end

   

   function new(string name = "");     

      super.new(name);     

   endfunction

endclass



class packet_B extends packet_base;



   rand int b;



   `ovm_object_utils_begin(packet_B);

   `ovm_field_int(b, OVM_ALL_ON)

   `ovm_object_utils_end

   

   function new(string name = "");     

      super.new(name);     

   endfunction

endclass



class packet_sequencer extends ovm_sequencer#(packet_base, packet_base);

   `ovm_sequencer_utils(packet_sequencer);

   

   function new(string name, ovm_component parent);   

      super.new(name, parent);

      `ovm_update_sequence_lib

   endfunction

endclass



class packet_driver extends ovm_driver#(packet_base, packet_base);

  `ovm_component_utils(packet_driver)



  function new(string name, ovm_component parent);     

    super.new(name,parent);

  endfunction



  task run();

     packet_base next_packet;



     // This driver does nothing except for printing

     forever begin

        seq_item_port.get_next_item(next_packet);

        ovm_report_info("NEXT_PACKET",{"The next packet is:\n", next_packet.sprint()});

        seq_item_port.item_done(next_packet);

     end                

  endtask 

endclass



class packet_env extends ovm_env;

   `ovm_component_utils(packet_env);



   packet_sequencer sequencer;

   packet_driver driver;

   

   function new(string name, ovm_component parent);   

      super.new(name, parent);

   endfunction // new



   function void build();

      super.build();

      sequencer = packet_sequencer::type_id::create("packet_sequencer", this);

      driver = packet_driver::type_id::create("packet_driver", this);

   endfunction

   

   function void connect();

      super.connect();

      driver.seq_item_port.connect(sequencer.seq_item_export);

      driver.rsp_port.connect(sequencer.rsp_export);

   endfunction

endclass



class packet_seq_base extends ovm_sequence#(packet_base);



  `ovm_sequence_utils(packet_seq_base, packet_sequencer)



   // constrain this field to control packet_type

   rand packet_type_t packet_type;

   

   packet_A p_A;

   packet_B p_B;

   

  function new(string name = "packet_seq_base");

    super.new(name);

  endfunction

endclass

endpackage



package test_pkg;

import ovm_pkg::*;

import packet_pkg::*;

`include "ovm_macros.svh"



class specific_seq extends packet_seq_base;

   `ovm_sequence_utils(specific_seq, packet_sequencer)



   function new(string name = "specific_seq");

      super.new(name);

   endfunction // new



   // in a specific sequence:

   // 1. randomize to choose the next packet

   // 2. use the sequencer built-in factory

   // to create the item, randomize and send it

   

   task body();  

     forever begin



        randomize();

        

        case(packet_type)

          A : `ovm_do_with(p_A, {p_A.a == 5;}) 

          B : `ovm_do_with(p_B, {p_B.b == 6;}) 

        endcase



        #1;

     end

  endtask

endclass  



class test extends ovm_test;

   `ovm_component_utils(test);



   packet_env env;

   

   function new(string name = "test", ovm_component parent=null);

      super.new(name,parent);

   endfunction

   

  virtual function void build();

     super.build();



     env = packet_env::type_id::create("env", this);

     set_config_string("env.sequencer","default_sequence", "specific_seq");

  endfunction

endclass                                 

endpackage



module top;

   import ovm_pkg::*;

   import packet_pkg::*;

   import test_pkg::*;



   initial begin      

      run_test();

   end

endmodule

  |  permalink

Back Next