Verification Martial Arts: A Verification Methodology Blog

Archive for October, 2010

Accelerating Design Verification with Virtual CPU models

Posted by Srivatsa Vasudevan on 29th October 2010

Srivatsa Vasudevan, Sr Staff CAE, Synopsys Inc & Filip Thoen, Product Architect, Synopsys Inc.

In today’s SOC architectures, one or more on-chip core(s) or CPU(s), like ARM or MIPS, are often used to provide flexibility in the system, through the use of embedded software. Besides executing software functionality, they program the hardware peripherals and perform I/O with them. Here, from a low-level hardware perspective the CPU is typically performing control and data plane functions.

virtual_models

Let’s look at this from a SoC verification perspective: in such cases, besides being able to drive the appropriate stimuli for the tests, the RTL simulation of the core(s)/CPU(s) doesn’t provide any additional value to a verification engineer. These core(s)/CPU(s) are typically pre-validated by their IP supplier, and hence don’t need to be validated again.

Running a performance profile on simulations of such SoCs reveals that a majority of the events simulated are typically within the CPU, which is often not a portion of the DUT being verified. Consequently, valuable verification time is lost in debug, and no additional information is gained from the simulation of these cores/CPUs. Often, verification teams use embedded software tests running on these core(s)/CPU(s) to validation individual IPs and/or to perform system integration validation. These software tests will program the different peripheral(s) / module(s) being tested, exercise them and observe and validate the result for correctness. Other software scenarios include the testing of the SoC’s boot sequence, which is typically performed by boot code executed by these core(s)/CPU(s).

(Note: Click on the figure if it appears too smal in your browser, Thanks!)

In situations like this, it often makes sense to replace the event-heavy CPU RTL model with a transaction –level model (TLM), typically called an instruction-set simulator (ISS) in case of a CPU or core. These models are written in C/C++ or SystemC, and depending on the abstraction level used, can run up to 100+ MIPS standalone. Such a model will execute the actual embedded software program binaries and issue the appropriate (bus) transactions to the peripheral(s) / module(s) being verified. As a result, the events originating from the simulating the CPU are now removed from the RTL simulation, and the net effect observed is a significant simulation acceleration while obtaining the required results. Moreover, non-interesting events, like the fetching of instructions from off- or on-chip ROM/RAM, requiring a high number of events in the bus-memory controller-memory chain, can be avoided in the RTL simulation by shadowing these memories in the virtual CPU model.

image

Several system level models for popular cores/CPUs are now available as part of the Synopsys Designware® System-Level Library product, including ARM, MIPS and PowerPC architectures. Combined with a pin level transactor, which matches the transaction level interface of the TLM model to the pin-level interface of the CPU bus, a virtual model of the core/CPU present in the SoC can be set up. Integration & deployment of this is straightforward: the virtual CPU model is a direct pin-level replacement of the RTL CPU, simply requiring a SystemC integration as historically supported by VCS.

There are several ways of implementing this keeping in mind re-use requirements, configurations and the stage at which verification is being carried out. In the figure above, the CPU has been replaced by a virtual model along with a pin level transactor. The CPU still runs the same embedded directed software test code as before, but with a significant simulation speed-up, ranging between 3-20x depending on the design specific parameter like RTL size, speed & number of other (high-speed) modules, testbench overhead, etc. Another significant benefit is the gain in debugability, and the associated increase in productivity. These TLM models allow commercial embedded software debuggers to be connected to the simulation, allowing verification (and software) engineers to (interactively) debug the running verification or boot software program. With the RTL of the CPU in place, this is typically not realizable.

What do you think of this concept? Interesting? How do you handle such situations? Drop me a line.

-Srivatsa

Posted in Transaction Level Modeling (TLM) | 1 Comment »

Using VMM template Generator to ramp up your testbench development

Posted by Amit Sharma on 25th October 2010

Amit Sharma, Synopsys
‘vmmgen’, the template generator for creating robust, extensible VMM compliant environments, has been available for a long time with VMM and it was upgraded significantly with VMM1.2. Though the primary functionality of ‘vmmgen’ is to help minimize VIP and environment development cycle by providing detailed templates for developing VMM Compliant verification environments, a lot of folks also use it to quickly understand how different VMM base classes can be used in different contexts. This is done as the templates uses a rich set of the latest VMM features to ensure the appropriate base classes and their features are picked up optimally.

Given that it has a wide user interaction mechanism which provides available features and options to the user, the user can pick up the modes which are most relevant to his or her requirement. It also provides them the option to provide their own templates thus providing a rich layer of customization. Based on the need, one can generate individual templates of different verification components or they can generate a complete verification environment which comes with a ’Makefile’ and an intuitive directory structure, thus propelling them on their way to catch the first set of bugs in their DUTs. I am sure all of you know where to pick up ‘vmmgen’ form. It available in the <VMM_HOME>/Shared/bin area or in $VCS_HOME/bin

Some of the rich set of features available now includes:

• Template Options:

– Complete environment generation

– Individual templates generation

• Options to create Explicitly phased environments or Implicitly phased environment or to mix Implicitly phased components and Explicitly phased components

• Usage of VMM Shorthand macros

• Creating RAL based environment, and providing Multiplexed domain support if required

• Hooking up VMM Performance Analyzer at the appropriate interfaces

• Hooking up the DS Scoreboard at the relevant interfaces (with options to chose from a range of integration options, e.g. : through callbacks, through TLM2.0 analysis ports, connect directly through to transactors, channels or notifications)

• Ability to hook up different generators (atomic, scenario, Multistream generators) at different interfaces

• Creating a scenario library and Multistream scenario creation

• Multi-driver generator support for different kinds of transactions in the same environment

• Factory support for transactions, scenarios and multi stream scenarios. Sample factory testcase which can explain the usage of transaction override from a testcase.

• ‘RTL config’ support for drivers and receivers.

• Various types of unidirectional and bi-directional TLM connections between generator and driver.

• Analysis ports/exports OR parameterized notify observers to broadcast the information from monitor to scoreboard and coverage collectors.

• Multi test concatenation support and management to run the tests

• Creating portable Interface wrapper object, and setting up interface connections to the testbench components using vmm_opts::set_object/get_object_obj

• Creating a Generic slave component

• Option to use default names or user provided names for different components

As you can see the above list itself is quite comprehensive and let me tell you that that it is not exhaustive as there are many more features in vmmgen.

With respect to the usage as well, there are multiple flavors. In the default mode, the user is taken through multiple detailed choices/options as he is creating/connecting different components in his verification environment. However, some folks might want to use ‘vmmgen’ within their own wrapper script/environment and for them there are options to generate the environments by providing all required options in the command line or through a configuration file… Some of these switches include

-SE [y/n] : Generates a complete environment with sub-environments

-RAL [y/n] : Create RAL based verification environments

-RTL [y/n] : Generates RTL configuration for the environment

-ENV <name>, -TR <name> : Provide the name for the environment class and transaction classes. names for multiple transaction class names can be provide as well:

vmmgen –l sv –TR tr1+tr2

-cfg_file <file_name> : Option to provide a configuration file for the options

There is an option to generate an environment quickly by taking the user through the minimum number of questions (-q).

Additionally, the user can provide his or her own templates through the –L <template directory> option.

As far as individual template generation goes, you have the complete list. Here, I am outlining this down for reference:

image

I am sure a lot of you have already been using ‘vmmgen’. For those, who haven’t, I encourage you to try out the different options with it. I am sure you will find this immensely useful and it will not only help you create verification components and environments quickly but will also make sure they are optimal and appropriate based on your requirements.

Posted in Automation, Coding Style, Customization, Modeling Transactions, Organization, Performance Analyzer, Scoreboarding, Tools & 3rd Party interfaces, VMM infrastructure | No Comments »

Setting data members for factory-created objects

Posted by Avinash Agrawal on 11th October 2010

Avinash Agrawal, Corporate Applications, Synopsys

One question asked by verification engineers is that given that we are using the VMM factory, how do we assign the data members of VMM class factory service while calling the create_instance method ?

For example, the create_instance() method of class factory service always calls
the class constructor with default arguments. Therefore, it would appear that extra arguments
cannot be passed to the class instance class. i.e., there is no way to pass
additional arguments for class members with the following statements:

  tr = ahb_trans::create_instance(this, "Ahb_Tr0", `__FILE__, `__LINE__);

The answer is that while you cannot use the create_instance() function to initialize   ?
data members, you can use any of the following methods to deal with this assignment:
1. By using virtual function/task set_* in the base class and derived class, and the
   arguments are passed from the arguments list of set_* function/task. But there
   is a limitation with this as the set_* function/task arguments for the base
   class and the derived class must be the same.

2. By using vmm_opts::set_* and vmm_opts::get_* combination to set the value of
   properties of class. 

Examples:

1. By using set_* to pass arguments as described in point 1:

////////////////////
//Source code
////////////////////
`define VMM_12
program P;
`include "vmm.sv"

// Define base class
class ahb_trans extends vmm_data;
  `vmm_typename(ahb_trans00)
  rand int addr;
  static vmm_log log = new("ahb_trans", "object");

  `vmm_data_member_begin(ahb_trans)
    `vmm_data_member_scalar(addr,	DO_ALL)
  `vmm_data_member_end(ahb_trans)

  virtual function void set_data(int addr=0, int data=0);	// <-- Two arguments
    this.addr = addr;
  endfunction

  virtual function void display_data();
    `vmm_note(log, $psprintf("ahb_trans.addr=='h%0h", this.addr));
  endfunction

  `vmm_class_factory(ahb_trans)
endclass

// Define derived class
class my_ahb_trans extends ahb_trans;
  `vmm_typename(my_ahb_trans)
  rand int data;

  static vmm_log log = new("my_ahb_trans", "object");

  `vmm_data_member_begin(my_ahb_trans)
    `vmm_data_member_scalar(data,		DO_ALL)
  `vmm_data_member_end(my_ahb_trans)

  virtual function void set_data(int addr=0, int data=0);	// <-- Two arguments
    this.addr = addr;
    this.data = data;
  endfunction

  virtual function void display_data();
    `vmm_note(log, $psprintf("my_ahb_trans.addr=='h%0h, my_ahb_trans.data=='h%0h", this.addr, this.data));
  endfunction

  `vmm_class_factory(my_ahb_trans)
endclass

class env extends vmm_env;

   ahb_trans tr;

   function new;
      super.new("ENV");
   endfunction;

   function void build;
      super.build;

     ahb_trans::override_with_new("@%*", my_ahb_trans::this_type, log, `__FILE__, `__LINE__);
     tr = ahb_trans::create_instance(this, "Ahb_Tr0", `__FILE__, `__LINE__); 

     if(!(tr.get_typename == "class P.my_ahb_trans"))
        `vmm_error(log,"ERROR");

     tr.set_data(32'h5555_5555, 32'haaaa_aaaa);	// <-- Call set_* after create_instance
     tr.display_data();

   endfunction

endclass

initial begin
  env env = new();
  env.run;
end

endprogram

////////////////////
//Simulation Result
////////////////////
Normal[NOTE] on my_ahb_trans(object) at                    0:
    my_ahb_trans.addr=='h55555555, my_ahb_trans.data=='haaaaaaaa
Simulation PASSED on /./ (/./) at                    0 (0 warnings, 0 demoted errors & 0 demoted warnings)

2. By using vmm_opts::set_* and vmm_opts::get_* combination as described in point 2:

////////////////////
//Source code
////////////////////
`define VMM_12
program P;
`include "vmm.sv"

// Define base class
class ahb_trans extends vmm_data;
  `vmm_typename(ahb_trans00)
  rand int addr;
  static vmm_log log = new("ahb_trans", "object");

  `vmm_data_member_begin(ahb_trans)
    `vmm_data_member_scalar(addr,	DO_ALL)
  `vmm_data_member_end(ahb_trans)

  virtual function void set_data();
    this.addr = vmm_opts::get_int ("ADDR", 0, "Value set for addr");
  endfunction

  virtual function void display_data();	//<-- no arguments passed, so there is no limitation on number of arguments
    `vmm_note(log, $psprintf("ahb_trans.addr=='h%0h", this.addr));
  endfunction

  `vmm_class_factory(ahb_trans)
endclass

// Define derived class
class my_ahb_trans extends ahb_trans;
  `vmm_typename(my_ahb_trans)
  rand int data;

  static vmm_log log = new("my_ahb_trans", "object");

  `vmm_data_member_begin(my_ahb_trans)
    `vmm_data_member_scalar(data,		DO_ALL)
  `vmm_data_member_end(my_ahb_trans)

  virtual function void set_data();	//<-- no arguments passed, so there is no limitation on number of arguments
    this.addr = vmm_opts::get_int ("ADDR", 0, "Value set for addr");
    this.data = vmm_opts::get_int ("DATA", 0, "Value set for data");
  endfunction

  virtual function void display_data();
    `vmm_note(log, $psprintf("my_ahb_trans.addr=='h%0h, my_ahb_trans.data=='h%0h", this.addr, this.data));
  endfunction

  `vmm_class_factory(my_ahb_trans)
endclass

class env extends vmm_env;

   ahb_trans tr;

   function new;
      super.new("ENV");
   endfunction;

   function void build;
      super.build;

     vmm_opts::set_int("ADDR", 32'h55,null);	//	<-- Call vmm_opts::set_*
     vmm_opts::set_int("DATA", 32'haa,null);

     ahb_trans::override_with_new("@%*", my_ahb_trans::this_type, log, `__FILE__, `__LINE__);
     tr = ahb_trans::create_instance(this, "Ahb_Tr0", `__FILE__, `__LINE__); 

     if(!(tr.get_typename == "class P.my_ahb_trans"))
        `vmm_error(log,"ERROR");

     tr.set_data();
     tr.display_data();

   endfunction

endclass

initial begin
  env env = new();
  env.run;
end

endprogram

////////////////////
//Simulation Result
////////////////////
Normal[NOTE] on my_ahb_trans(object) at                    0:
    my_ahb_trans.addr=='h55, my_ahb_trans.data=='haa
Simulation PASSED on /./ (/./) at                    0 (0 warnings, 0 demoted errors & 0 demoted warnings)

Posted in VMM, VMM infrastructure | No Comments »