Verification Martial Arts: A Verification Methodology Blog

Archive for the 'SystemC/C/C++' Category

SNUG-2012 Verification Round Up – Miscellaneous Topics

Posted by paragg on 29th March 2013

In my final installment of the series of blogs summing up the various SNUG verification papers of 2012, I try to cover the user papers on the Design IP/Verification IP and SystemC and SystemVerilog co-simulation. Please find my earlier blogs on the other domains here: System Verilog Language, Methodologies & VCS technologies

DesignWare core USB3.0 Controller (DWC_usb3) can be configured as a USB3.0 Device Controller. When verifying a system that comprises a DWC_usb3 Device Controller, the verification environment is responsible for bringing up the DWC_usb3 Device Controller to its proper operation mode to communicate with the USB3.0 Host. The paper Integrating DesignWare USB3.0 Device Controller In a UVM-based Testbench from Ning Guo of Paradigm Works describes the process of configuring and driving the DWC_usb3 Device Controller in a UVM based verification environment using the Discovery USB 3.0 Verification IP. This paper describes how the verification environment needs to be created so that it’s highly configurable and reusable.

The AMBA 4 ACE specification enables system level cache coherency across clusters of multicore processors, such as the ARM Cortex-A15 and Cortex-A7 MPCore™ processors .This ensures optimum performance and power efficiency of complex SoC designs. However, the design complexity associated with these capabilies is also higher.  And it throws up new verification challenges.  In the paper, Creating AMBA4 ACE Test Environment With Discovery VIP”, Whitney Huang, Sean Chou, MediaTek Inc, demonstrates how to tackle complex verification challenges increase their verification productivity by using Synopsys Discovery AMBA ACE VIP.

The paper, Verification Methodology of Dual NIC SOC Using VIPs by A.V. Anil Kumar, Mrinal Sarmah, Sunita Jain of Xilinx India Technology Services Pvt. Ltd, talks about how various features of Synopsys PCIe and Ethernet Verification IPs can be exploited to help in the efficient verification of the DUT across various traffic configurations. The paper explores how the VIP Application Programming Interface (API)s can leveraged in the  tests cases to reach high  functional coverage numbers  in a very short duration. They also show how a dual NIC verification environment can effectively use Ethernet VIP APIs to test various Media Access Control (MAC) features. Finally conclude how of the implementation can be used across future revisions of their design.

The ability to analyze the performance of the SoC at the early stage of the design can make a significant different to the end product.  This can lead to more accurate and an earlier estimate of the desired performance that is expected.  Dayananda Yaraganalu Sadashivappa, Igal Mariasin, Jayaprakash Naradasi of SanDisk India Device Design Centre Pvt. Ltd., in the paperGeneric MLM environment for SoC Performance Enhancement”, outlines the solution that was found by using the Synopsys VIP models. The VIPs were used in conjunction with interconnect, which in this case is a Multi-Layer-Matrix (MLM). The environment was built leveraging the VMM base classes. The VMM multiple stream scenario (vmm_ms_scenario) base class was used to create the traffic across the matrix, and the performance meters were constructed using the base classes. The callbacks were leverage appropriately help in collating the statistics. Multiple knobs were used to make the environment generic and configurable. The approach helped in finding multiple performance bugs which could not have been easily found using conventional verification.

In the paper, “User Experience Verifying Ethernet IP Core”, Puneet Rattia of Altera Corporation, presents his experience with verifying the Altera® 40-100Gbps Ethernet IP core utilizing VMM environment while integrating the Ethernet VIP from Synopsys. He explains how he created a full suite of system and blocks level regression tests and then goes on to show how he  utilizes the coverage mapping capabilities of VCS to merge the results across these various testbenches and produce meaningful reports. Besides showing how to reuse the verification infrastructure at the SoC level, the paper also demonstrates how they went in for horizontal reuse by integrating the reference SystemC based models developed and prototyped in the early phase of the project.

UVM 1.x includes support for the communication interfaces defined by the SystemC TLM-2.0 standard. This enables integration of SystemC TLM-2.0 IP into a SystemVerilog UVM verification environment. Dr David Long, John Aynsley, Doug Smith, Doulos in the paper A Beginner’s Guide to Using SystemC TLM-2.0 IP with UVMdescribes how this is done best. They talk about the fact that the connection between SystemC and SystemVerilog currently requires a tool specific interface such as Synopsys Transaction Level Interface (TLI). This paper begins with a brief overview of TLM-2.0 aimed at novice users. It then discusses the steps required to add a SystemC TLM-2.0 model into a SystemVerilog UVM environment and simulate it with VCS. At each step, issues that users will face are explored and suggestions made for practical fixes, showing the relevant pieces of code. Finally, the paper gives a summary of areas where the UVM implementation of TLM-2.0 differs from the SystemC standard and proposes workarounds to ensure correct communication between the SystemVerilog and SystemC domains.

There is an inherent need to enable the horizontal reuse of components created during the architecture and exploration stage. Subhra S Bandyopadhyay, Pavan N M, Intel Technology India Pvt. Ltd, in Integrating SystemC OSCI TLM 2.0 Models to OVM based System Verilog Verification Environments talks about how  theur architecture team creates SystemC models  for early performance analysis and accelerated software development. In OVM-based verification environment, the objective was to reuse this model as a reference model and thus helped in reducing the overall environment bring-up time. The challenge was not only to integrate the SystemC model in the OVM-based verification environment but also to be able to efficiently send transactions from SV to SystemC and vice versa. This paper explores the successful integration of SystemC TLM2 components in OVM based verification environments and also highlight how the VCS TLI (Transaction Level Interface) adapters help TLM2.0 sockets in SystemC to communicate with those in SV and vice versa.

Truly, I feel overwhelmed by the numbers of papers and the interesting use of technology across a variety of domains on which user share their experiences across the various SNUG conferences. As we speak, the SNUG events for 2013 have started, and the stage is all set for a new set of very informative and interesting sessions. I am sure most of you would be attending the SNUIG conferences in your area. . You can find the detailed schedule of those here.

Posted in Announcements, Automation, Callbacks, Coding Style, Communication, Reuse, Structural Components, SystemC/C/C++, SystemVerilog, Transaction Level Modeling (TLM), Tutorial, UVM, VMM | Comments Off

VCS Built-in TLI connectivity for UVM to SystemC TLM 2.0

Posted by vikasg on 20th September 2012

Vikas Grover | Sr. Manager, Central Verification | AMD-India

One of the challenges faced in SOC verification is to validate the designs in mixed language and mixed  abstraction level. SystemC is widely used language to define the system model at higher level of abstraction.  SystemC is an IEEE standard language for System Level modeling and it is rich with constructs for  describing models at various levels of abstraction i.e. Untimed, Timed, Transaction Level, Cycle Accurate,  and RTL. The transaction level model simulates much faster than RTL model, besides OSCI defined the TLM  2.0 interface standard for SystemC which enables SystemC model interoperability and reuse at transaction  level.

On the other side, SystemVerilog is a unified language for design and verification. It is effective for designing advance testbenches for both RTL and Transaction level models, since it has features like constraint randomization for stimulus generation, functional coverage, assertions, object oriented constructs(like class,inheritance etc). Early availability of standard methodologies (providing framework and testbench coding guidelines for resue) like VMM, OVM, UVM enabled wide adoption for System Verilog in industry. The UVM 1.0 Base Class Library which was   released on Feb 2011  includes OSCI TLM 2.0 socket interface to enable interoperability for UVM with SystemC . Essentially it allows UVM testbench to include SystemC TLM 2.0 reference models. The UVM testbench can pass (or receive) transactions from SystemC models. The transaction passed across System Verilog ßàSystemC could be TLM 2.0 generic payload OR uvm_sequence_item. The implementation of UVM to SC TLM 2.0 communication is vendor dependent.

Starting with with the 2011.03 release, VCS provides a new TLI adaptor which enables UVM TLM 2.0 sockets to communicate with SC TLM 2.0 based environment to pass transactions across language domains.  You can also check out  a couple of earlier post from John Aynsley, (VMM-to-SystemC Communication Using the TLI and  Blocking and Non-blocking Communication Using the TLI) on SV-SystemC communication using TLI.   In this Blog, I am going to describe VCS TLI connectivity mechanism between UVM and SystemC. There are other advance TLI features in VCS ( like direct access of data, invoking task/functions  across SV and SC language),  message unification across UVM-SC, transaction debug techniques, extending TLI adaptor for user defined interface other than VMM/UVM/TLM2.0 which can be written about on later.

With the support for TLM2.0 interfaces in both UVM and VMM, the importance of OSCI TLM2.0 across both SystemC and SystemVerilog is now apparent. UVM provides the following TLM2.0 socket interfaces (for both blocking and non-blocking communication)

  • uvm_tlm_b_initiator_socket
  • uvm_tlm_b_target_socket
  • uvm_tlm_nb_initiator_socket
  • uvm_tlm_nb_target_socket
  • uvm_analysis_port
  • uvm_subscriber

SystemC TLM2.0 consists of following TLM 2.0 interface

  • tlm_initiator_socket
  • tlm_target_socket
  • tlm_analysis_port

The Built-in TLI adaptor solution for VCS is a general purpose solution to simplify the transaction passing across UVM and  SystemC as shown below. The transactions can be TLM 2.0 generic payload OR uvm_sequence_item object. The UVM 1.0 does have the TLM 2.0 generic payload class as well.

The Built-in TLI adaptor is available as a pre-compiled library with VCS. The user would need to follow two simple steps to include the TLI adaptor in his/her verification environment.

  1. Include a header file in System Verilog and SystemC code. The System Verilog header file provides a package which implements the bind function parameterized on uvm_sequence_item object.
  2. Invoke the bind function on System Verilog and SystemC side to connect each socket across language.  The bind function has a string argument which must be unique for each socket connection across System Verilog and SystemC.

The code snippet for above steps is shown below. The TLI adaptor code is highlighted in orange/blue color.  The UVM Initiator  “initiator_udf” from System Verilog is driving SystemC Target “ target_udf” using the  TLM  blocking socket.

The TLI adaptor bind function uses the unique string “str_udf_pkt” to identify the socket connectivity across SystemVerilog and SystemC domain.  For multiple sockets, the user needs to invoke the TLI bind function once for each socket. The TLI adaptor supports both blocking and non-blocking transport interfaces for sockets to communicate across System Verilog and SystemC.

Thus, the Built-in UVM-SC TLI adaptor capability of VCS ensures that SystemC can be connected seamlessly in UVM based verification environment.

Posted in Communication, Interoperability, SystemC/C/C++, Tools & 3rd Party interfaces, Transaction Level Modeling (TLM) | 1 Comment »

Blocking and Non-blocking Communication Using the TLI

Posted by John Aynsley on 31st March 2011

John Aynsley, CTO, Doulos

In the previous blog post I introduced the VCS TLI Adapters for transaction-level communication between SystemVerilog and SystemC. Now let’s look at the various coding styles supported by the TLI Adapters, and at the same time review the various communication options available in VMM 1.2.

We will start with the options for sending transactions from SystemVerilog to SystemC. VMM 1.2 allows transactions to be sent through the classic VMM channel or through the new-style TLM ports, which come in blocking- and non-blocking flavors. Blocking means that the entire transaction completes in one function call, whereas non-blocking interfaces may required multiple function calls in both directions to complete a single transaction:

image

On the SystemVerilog side, transactions can be sent out through blocking or non-blocking TLM ports, through VMM channels or through TLM analysis ports. On the SystemC side, transactions can be received by b_transport or nb_transport, representing the loosely-timed (LT) and approximately-timed (AT) coding styles, respectively, or through analysis exports. In the TLM-2.0 standard any socket supports both the LT and AT coding styles, although SystemVerilog does not offer quite this level of flexibility, and hence neither does the TLI.

Now we will look at the options for sending transactions from SystemC back to SystemVerilog. Not surprisingly, they mirror the previous case:

image

On the SystemC side, transactions can be sent out from LT or from AT initiators or through analysis ports. On the SystemVerilog side, transactions can be received by exports for blocking- or non-blocking transport, by vmm_channels, or by analysis subscribers.

Note the separation of the transport interfaces from the analysis interfaces in either direction. The transport interfaces are used for modeling transactions in the target application domain, whereas the analysis interfaces are typically used internally within the verification environment for coverage collection or checking.

In the SystemVerilog and SystemC source code, the choice of which TLI interface to use is made when binding ports, exports, or sockets to the TLI Adapter, for example:


// SystemVerilog
`include “tli_sv_bindings.sv”
import vmm_tlm_binds::*;           // For port/export
import vmm_channel_binds::*;       // For channel

tli_tlm_bind(m_xactor.m_b_port,    vmm_tlm::TLM_BLOCKING_EXPORT,    “sv_tlm_lt”);
tli_tlm_bind(m_xactor.m_nb_port,   vmm_tlm::TLM_NONBLOCKING_EXPORT, “sv_tlm_at”);
tli_tlm_bind(m_xactor.m_b_export,  vmm_tlm::TLM_BLOCKING_PORT,      “sc_tlm_lt”);
tli_tlm_bind(m_xactor.m_nb_export, vmm_tlm::TLM_NONBLOCKING_PORT,   “sc_tlm_at”);
tli_channel_bind(m_xactor.m_out_at_chan, “sv_chan_at”, SV_2_SC_NB);

// SystemC
#include “tli_sc_bindings.h”
tli_tlm_bind_initiator(m_scmod->init_socket_lt, LT, “sc_tlm_lt”,true);
tli_tlm_bind_initiator(m_scmod->init_socket_at, AT, “sc_tlm_at”,true);
tli_tlm_bind_target   (m_scmod->targ_socket_lt, LT, “sv_tlm_lt”,true);
tli_tlm_bind_target   (m_scmod->targ_socket_at, AT, “sv_tlm_at”,true);
tli_tlm_bind_target   (m_scmod->targ_socket_chan_at, AT, “sv_chan_at”,true);


Note how the tli_tlm_bind calls require you to specify in each case whether the LT or AT coding style is being used. The root cause of this inflexibility is certain language restrictions in SystemVerilog, in particular the lack of multiple inheritance, which makes it harder to create sockets that support multiple interfaces. Hence, in SystemVerilog, the blocking- and non-blocking interfaces get partitioned across multiple ports and exports. In the SystemC TLM-2.0 standard there is only a single kind of initiator socket and a single kind of target socket, each able to forward method calls of any of the core interfaces, namely, the blocking transport, non-blocking transport, direct memory, and debug interfaces.

In summary, the VCS TLI provides a simple and straightforward mechanism for passing transaction in both directions between SystemVerilog and SystemC by exploiting the TLM-2.0 standard.

Posted in SystemC/C/C++, SystemVerilog, Transaction Level Modeling (TLM) | 1 Comment »

VMM-to-SystemC Communication Using the TLI

Posted by John Aynsley on 22nd March 2011

John Aynsley, CTO, Doulos

I have said several times on this blog that the presence of TLM-2.0 features in VMM 1.2 should ease the task of communicating between a SystemVerilog test bench and a SystemC reference model. Now, at last, let’s see how to do this – using the VCS TLI or Transaction Level Interface from Synopsys.

The parts of the TLI in question are the VCS TLI Adapters between SystemVerilog and SystemC. These adapters exploit the TLM-2.0-inspired features introduced into VMM 1.2 on the SystemVerilog side and the OSCI TLM-2.0 standard itself on the SystemC side in order to pass transactions between the two language domains within a VCS simulation run. The TLI Adapters do not provide a completely general solution out-of-the-box for passing transactions between languages in that they are restricted to passing TLM-2.0 generic payload transactions (as discussed in a previous blog post). However, the Adapters can be extended by the user with a little work.

Clearly, the VCS TLI solution will only be of interest to VCS users. As an alternative to the VCS TLI, it is possible to pass transactions between SystemVerilog and SystemC using the SystemVerilog DPI as described in SystemVerilog Meets C++: Re-use of Existing C/C++ Models Just Got Easier, and the Accellera VIP Technical Subcommittee are discussing a proposal to add a similar capability to UVM.

If you want to pass user-defined transactions between SystemVerilog and SystemC you are going to have to jump through some hoops, whether you choose to use the VCS TLI or the DPI. However, for the TLM-2.0 generic payload, the VCS TLI provides a simple ready-to-use solution. Let’s see how it works.

image

The TLI Adapters are provided as part of VCS. All you have to do is to include the appropriate file headers in your source code on both the SystemVerilog and SystemC sides, as shown on the diagram. The adapters themselves get compiled and instantiated automatically. The SystemVerilog side needs to use the VMM TLM ports, exports, or channels (as described in previous blog posts). The SystemC side needs to use the standard TLM-2.0 sockets. You then need to add a few extra lines of code on each side to bind the two sets of sockets together, and the TLI Adapters take care of the rest.
From the point of view of the source code, the adapter is invisible apart from the presence of the header files. Each binding needs to be identified by giving it a name, with identical names being used on the SystemVerilog and SystemC sides to tie the two sets of ports or sockets together. Here is a trivial example:

// SystemVerilog
`include “tli_sv_bindings.sv”

vmm_tlm_b_transport_port #(my_xactor, vmm_tlm_generic_payload) m_b_port;

tli_tlm_bind(m_xactor.m_b_port, vmm_tlm::TLM_BLOCKING_EXPORT, “abc”);

// SystemC
#include “tli_sc_bindings.h”

tlm_utils::simple_target_socket<scmod>  targ_socket_lt;

tli_tlm_bind_target (m_scmod->targ_socket_lt, LT, “abc”, true);


Note that the same name “abc” has been used on both the SystemVerilog and SystemC sides to tie the two ports/sockets together. On the SystemVerilog side we can now construct transactions and send them out through the TLM port:

// SystemVerilog
tx = new;
assert( tx.randomize() with { m_command != 2; } );
m_b_port.b_transport(tx, delay);


On the SystemC side, we receive the incoming transaction:

// SystemC
void scmod::b_transport(tlm::tlm_generic_payload& tx, sc_time& delay) {

tx.set_response_status(tlm::TLM_OK_RESPONSE);
}

The TLI Adapter takes care of converting the generic payload transaction from SystemVerilog to SystemC, and also takes care of the synchronization between the two languages. The VCS TLI provides a great ready-made solution for this particular use case. In the next blog post I will look at the VCS TLI support for various TLM modeling styles.

Posted in SystemC/C/C++, Transaction Level Modeling (TLM) | 2 Comments »

Verification in the trenches: Transform your sc_module into a vmm_xactor

Posted by Ambar Sarkar on 19th January 2011

Dr. Ambar Sarkar, Chief Verification Technologist, Paradigm Works Inc.

Say you have SystemC VIP lying around, tried and true. More likely than not, they are BFMs that connect at the signal level to the DUT and have a procedural API supporting transaction level abstraction.

What would be the best way to hook these components up with a VMM environment? With VMM now being available in SystemC as well, you really want to make these models look and behave as vmm_xactor derived objects that interact seamlessly across the SystemC/SystemVerilog language boundary. Your VMM environment can thus take full advantage of your existing SystemC components. And your sc_module can still be used, just as before, in other non VMM environments!

Enough motivation. Can this be done? Since Syst
emC is really C++, and it supports multiple inheritance, is there a way to just create a class that inherits from both your SystemC component as well vmm_xactor?

Here is an example..

Originally, suppose you had a consumer bfm defined(keeping the example simple for illustration purposes).

   1:  SC_MODULE(consumer) {
   2:    sc_out<sc_logic>   reset;
   3:    sc_out<sc_lv<32> > sample;
   4:    
   5:    sc_in_clk    clk;
   6:      SC_CTOR(consumer_wrapper):    clk("clk"),    reset("reset"),   sample("sample") {
   7:    }
   8:    
   9:    . . .  
  10:  };

Solution Attempt 1) The first thing to try would be to simply create a new class called consumer_vmm as follows and define the required vmm_xactor methods.

   1:  class consumer_vmm : public consumer, public vmm_xactor 
   2:  {
   3:    consumer(vmm_object* parent, sc_module_name _nm) 
   4:           : vmm_xactor(_nm,"consumer",0,parent)
   5:              ,reset("reset") 
   6:              ,sample("sample") 
   7:              ,clk("clk")   
   8:       {   
   9:           SC_METHOD(entry);
  10:           sensitive << clk.pos();
  11:          . . .
  13:        
  14:       }
  15:      . . . define the remaining vmm_xactor methods as needed . . .
  16:  };
Unfortunately, this does not work. Reason? As it turns out, vmm_xactor also inherits from sc_module.So consumer_vmm will end up inheriting same sc_module through two separate classes, the consumer and the vmm_xactor. This is known as the Diamond Problem.  Check out for some fun reading 
at http://en.wikipedia.org/wiki/Diamond_problem. 
 
Okay, so what can be done? Well, luckily, we can get all of this to work reasonably well with some additional tweaks/steps. Yes, you will need to very slightly modify the original source code, but in a backward compatible way. 
 

Solution Attempt 2) Make the original consumer class  derive from vmm_xactor instead of sc_module. This is the only change to existing code, and this will be backward compatible since vmm_xactor inherits from sc_module as well. Of course, add any further vmm_xactor:: derived methods using the old api as needed.

   1:  class consumer: public vmm_xactor
   2:  {
   3:   public:
   4:    sc_out<sc_logic>   reset;
   5:    sc_out<sc_lv<32> > sample;
   6:    sc_in_clk    clk;
   7:    . . . 
   8:  }
 
 
Solution) Here are all the steps. It looks like quite a few steps, but other than creating the 
wrappers and hooking them, the rest of the steps remain the same regardless of whether you use 
the sc_module or the vmm_xactor. 

Step 1. Make the original consumer class  derive from vmm_xactor instead of sc_module. This is the only change to existing code, and this will be backward compatible since vmm_xactor inherits from sc_module as well. Of course, add any further vmm_xactor:: derived methods using the old api as needed.

   1:  class consumer: public vmm_xactor
   2:  {
   3:   public:
   4:    sc_out<sc_logic>   reset;
   5:    sc_out<sc_lv<32> > sample;
   6:    sc_in_clk    clk;
   7:    . . . 
   8:  }

step 2. define sc_module(consumer_wrapper) declare class that has the same set of pins as needed by consumer.

   1:  sc_module(consumer_wrapper) {
   2:    sc_out<sc_logic>   reset;
   3:    sc_out<sc_lv<32> > sample;
   4:    sc_in_clk    clk;
   5:    
   6:    sc_ctor(consumer_wrapper):    clk("clk"),    reset("reset"),   sample("sample") {
   7:    }
   8:      
   9:  };
 
step 3. declare pointers to instances(not instances)  to these wrappers in env class
   1:  class env: public vmm_group
   2:  {
   3:  public:
   4:     consumer *consumer_inst0;
   5:     consumer *consumer_inst1;
   6:     consumer_wrapper *wrapper0, *wrapper1;
   7:   . . .
   8:  }

step 4. in the connect_ph phase, connect the pins of consumer instances and the corresponding wrappers instances

   1:  virtual void env::connect_ph() {
   2:      consumer_inst0->reset(wrapper0->reset);
   3:      consumer_inst0->clk(wrapper0->clk);
   4:      consumer_inst0->sample(wrapper0->sample);
   5:   
   6:      consumer_inst1->reset(wrapper1->reset);
   7:      consumer_inst1->clk(wrapper1->clk);
   8:      consumer_inst1->sample(wrapper1->sample);
   9:  }
  10:     

Step 5. In the constructor for sc_top, after the  vmmm_env instance is created, make sure the pointers in the env point to the these wrappers

   1:  class sc_top : public sc_module
   2:  {
   3:  public: 
   4:    
   5:    vmm_timeline*  t1;
   6:    env*           e1;
   7:   
   8:    sc_out<sc_logic>   reset0;
   9:    sc_out<sc_lv<32> > sample0;
  10:    sc_in_clk    clk;
  11:   
  12:    sc_out<sc_logic>   reset1;
  13:    sc_out<sc_lv<32> > sample1;
  14:      
  15:    consumer_wrapper wrapper0;
  16:    consumer_wrapper wrapper1;
  17:   
  18:    SC_CTOR(sc_top):
  19:      wrapper0("wrapper0")
  20:      ,wrapper1("wrapper1")
  21:      ,reset0("reset0")
  22:      ,sample0("sample0")
  23:      ,reset1("reset1")
  24:      ,sample1("sample1")
  25:      ,clk("clk")
  26:     {
  27:        t1 = new vmm_timeline("timeline","t1");
  28:        e1 = new env("env","e1",t1);
  29:   
  30:        e1->wrapper0 = &wrapper0;
  31:        e1->wrapper1 = &wrapper1;
  32:   
  33:        vmm_simulation::run_tests();
  34:   
  35:        wrapper0.clk(clk);
  36:        wrapper0.reset(reset0);
  37:        wrapper0.sample(sample0);
  38:   
  39:        wrapper1.clk(clk);
  40:        wrapper1.reset(reset1);
  41:        wrapper1.sample(sample1);
  42:   
  43:     }
  44:   
  45:  };
 
 
So while it looks like a few more than we had hoped, you do it only once, and mechanically. Small price to pay for reuse. Maybe someone can create a simple script. 


 

Also, contact me if you want the complete example. The example also shows how you can add tlm ports as well.
 

This article is the 10th in the Verification in the trenches series. Hope you found this article useful. If you would like to hear about any other related topic, please comment or drop me a line at ambar.sarkar@paradigm-works.com. Also, if you are starting out fresh, please check out the free VMM1.2 environment generator.

 

Posted in Interoperability, SystemC/C/C++, VMM | 1 Comment »

Verification in the trenches: A SystemC implementation of VMM1.2

Posted by Ambar Sarkar on 16th December 2010

Dr. Ambar Sarkar, Chief Verification Technologist, Paradigm Works Inc.

VMM1.2 class library is now also implemented in SystemC(VMM-SC).

Will it help your project? Please take a few minutes to consider this, especially if you have been using or thinking about C/C++/SystemC models in your environment.

Following are the some use cases that I have come across or can anticipate among our clients. With each use case, I have put down some thoughts on why VMM-SC may(or may not) be of any benefit. Do you agree?

Use Case 1. Using SystemC as the primary verification language for unit level verification

Many teams today use SystemC as their primary verification language for all unit and system-level tests. However, with the increasing popularity of SystemVerilog, they often adopt a hybrid model. They do use C++/SystemC as the primary language for testbench creation, but complement it using SystemVerilog language features for assertions, functional coverage analysis, and constrained random generation.

Such teams often consider moving to SystemVerilog based environments, but are concerned about the reuse of their existing code, and cannot justify the ROI against the resources needed to make the transition to SystemVerilog completely. Ideally, they would like to have a multi-language solution that can mix and match SystemVerilog and SystemC components.

For this class of users, VMM-SystemC can ease their adoption of a multi-language solution. First, they can create newer environments in VMM-SC, and encapsulate preexisting VIP within VMM-SC components using thin wrappers. Once transitioned to VMM-SC, they can easily interoperate with other VMM-SV based environments and components. As an added benefit of the SystemVerilog-SystemC interoperability, the VMM-SV applications such as RAL/Scoreboarding etc. can now be made available to the SystemC side.

Use Case 2. Using SystemC as the primary verification language for system-level verification

Some teams decide to write their system level verification environments primarily in C/C++, as it is often used by the SW team or in the lab. Depending on the sophistication of these teams, these environments may range from being simple directed C testbenches to those that are highly sophisticated and use SystemC. Adopting VMM-SC as the system-level methodology can make it easier to cleanly pull in various environments and components by encapsulating them as VMM objects and making them work together taking advantage of VMM-SC support for phasing, TLM ports etc.

For this class of users, adopting VMM-SC as the top-level glue environment will be a big win.

Use Case 3. Planning to move to SystemVerilog and adopt industry standard practices.

Often, teams are willing to start from scratch for new projects as they realize their existing environments have become outdated and simply cannot scale. With the maturity of SystemVerilog, they would likely adopt it as the primary HVL language of choice. However, they would still like to preserve a number of previously developed components.

This is an ideal application for using VMM-SC. Pre-existing transactors can be converted to VMM-SC components by deriving them from vmm_xactor/vmm_unit classes(see 4.3 below). The new environment can now be written in VMM-SV, which can pull in the legacy components using VMM-SC/SV interoperability solution. All VMM features, such as cross language option setting, communicating transactions in a language agnostic way between source and target components using TLM, coordinated phasing etc. make the SystemVerilog adoption process much easier.

Use Case 4.  Using SystemC to develop ESL environments and reference models.

There are users who are primarily interested in creating models at various levels of abstraction. These models can be used in multiple applications, such as performance modeling and architectural exploration. In some cases, such models may not be of sufficient detail to use in functional verification.

At the minimum, such models should be created using TLM2.0 ports to enable easy plug and play in ESL contexts. Adopting VMM-SC as the primary methodology for developing such components can be of benefit, since it offers a rich set of features that can help in controlling and coordinating the components, while maintaining strong interoperability with verification environments.

 

So, to which one of these use cases do you belong? Any other use case that I missed?

This article is the 9th in the Verification in the trenches series. Hope you found this article useful. If you would like to hear about any other related topic, please comment or drop me a line at ambar.sarkar@paradigm-works.com. Also, if you are starting out fresh, please check out the free VMM1.2 environment generator.

Posted in SystemC/C/C++, Transaction Level Modeling (TLM) | 1 Comment »

You can also “C” with RAL.

Posted by S. Varun on 18th November 2010

The RAL C interface provides a convenient way for verification engineers to develop firmware code which can be debugged on a RTL simulation of the design. This interface provides a rich set of C API’s using which one can access fields, registers and memories included within the RAL model. The developed firmware code can be used to interface with the RAL model running on a SystemVerilog simulator using DPI (Direct Programming Interface) and can also be re-used as application-level code to be compiled on the target processor in the final application as illustrated in the figure below.

image

The “-gen_c” option available with “ralgen“ has to be used for this and that would cause the generator to generate the necessary files containing the API’s to interface to the C domain. The generated API’s can be used in one of two forms.

1. To interface to the System Verilog RAL model running on a System Verilog simulator using DPI and

2. As a pure standalone-C code designed to compile on the target processor.

Typically firmware runs a set of pre-defined sequences of writes/reads to the registers on a device performing functions for boot-up, servicing interrupts etc. You generally have these functions coded in C, and these would need to access the registers in the DUT. Using the RAL C model, these functions can be generated so that the firmware can now perform the register access through the SystemVerilog RAL model. Thus, this allows firmware and application-level code to be developed and debugged on a simulation of the design and the same functions can later be used as part of the device drivers to perform the same tasks on the hardware.

In the first scenario, when executing the C code within a simulation, it is necessary for the C code to be called by the simulation to be executed and hence the application software’s main() routine must be replaced by one or more entry points known to the simulation. All entry points must take at least one argument that will receive the base address of the RAL model to be used by the C code. The C-side reference is then used by the RAL C API to access required fields, registers or memories.

image

Consider a sequence of register accesses performed at the boot time of a router as defined in function system_bootup() shown below,

File : router_test.c

#ifdef VMM_RAL_PURE_C_MODEL

/*when used as a pure C model for the target processor */

int main() {

void *blk = calloc(410024,1);

system_bootup((void *) (((size_t)blk)>>2)+1);

}

#endif

void system_bootup (unsigned int blk){

unsigned int dev_id = 0xABCD;

unsigned int ver_num = 0×1234;

/* Invoking the generated RAL C APIs */

ral_write_DEV_ID_in_ROUTER_BLK(blk, &dev_id);

ral_write_VER_NUM_in_ROUTER_BLK(blk, &ver_num);

}

In the above example “ral_write_DEV_ID_in_ROUTER_BLK()” & “ral_write_VER_NUM_in_ROUTER_BLK()” are C API’s generated by “ralgen” to access registers named “DEV_ID” & “VER_NUM” located in a block named “ROUTER_BLK”. In general registers can be accessed using “ral_read_<reg>_in_<blk>” & “ral_write_<reg>_in_<blk>” macros present within the RAL-C interface.

The above C function can also be called from within a System Verilog testbench via DPI

File : ral_boot_seq_test.sv

import “DPI-C” context task system_bootup(int unsigned ral_model_ID);

program boot_seq_test();

initial

begin

router_blk_env env = new();

// Configuring the DUT

env.cfg_dut();

// Calling the C function using DPI

system_bootup(env.ral_model.get_block_ID()); // ‘ral_model ‘is the instance of the generated SV model in the env class

end

endprogram

In the example above, system_bootup is the service entry point which is called from the SV simulation and is passed the RAL Model reference. The ‘C’ code that is executed and simulation freezes till one of the registers accesses is made which then shifts the execution to the SV side.

image

The entire execution in ‘C’ is in ‘0’ time in the simulation timeline. The RAL C API hides the physical addresses of registers and the position and size of fields. The hiding is performed by functions and macros rather than an object-oriented structure like the native RAL model in SystemVerilog. This eliminates the need to compile a complete object-oriented model in an embedded processor object code with a limited amount of memory

Thus by using the RAL C interface one can develop a compact and efficient firmware code, while preserving as much as possible of the abstraction offered by RAL. I hope this was useful and do let me know your thoughts on the same if you plan to use this flow to meet some of your requirements of having your firmware and application-level code to be developed and debugged on a simulation of the design.

Please refer to the RAL userguide for more information. You can also refer to the example present within VCS installation located at $VCS_HOME/doc/examples/vmm/applications/vmm_ral/C_api_ex.

Posted in Register Abstraction Model with RAL, SystemC/C/C++, SystemVerilog, VMM | Comments Off

Blocking/Non-blocking Transport Adaption in VMM 1.2

Posted by John Aynsley on 1st September 2010

John Aynsley, CTO, Doulos

One neat feature of the SystemC TLM-2.0 standard is the ability provided by the so-called simple target socket to perform automatic adaption between the blocking and non-blocking transport calls; an initiator that calls b_transport can be connected to a target that implements nb_transport, and vice-versa. VMM 1.2 provides similar functionality using the vmm_connect utility.

vmm_connect serves four distinct purposes in VMM 1.2.

•    Connecting one channel port to another channel port, taking account of whether each channel port is null or actually refers to an existing channel object
•    Connecting a notify observer to a notification
•    Binding channels to transaction-level ports and exports
•    Binding a transaction-level port to a transaction-level export where one uses the blocking
transport interface and the other the non-blocking transport interface. This is the case we are considering here.

When making transaction-level connections I think of vmm_connect as covering the “funny cases”.

To illustrate, suppose we have a transactor that acts as an initiator and calls b_transport. The following code fragment also serves as a reminder of how to use the blocking transport interface in VMM:

class initiator extends vmm_xactor;
`vmm_typename(initiator)

vmm_tlm_b_transport_port  #(initiator, vmm_tlm_generic_payload) m_b_port;

virtual task run_ph;
forever begin: loop
vmm_tlm_generic_payload tx;

// Create valid generic payload
assert( randomized_tx.randomize() with {…} )
else `vmm_error(log, “tx.randomize() failed”);

$cast(tx, randomized_tx.copy());

// Send copy through port
m_b_port.b_transport(tx, delay);

// Check response status
assert( tx.m_response_status == vmm_tlm_generic_payload::TLM_OK_RESPONSE );


Further, suppose we have another transactor that acts as a target for nb_transport calls, and which therefore implements nb_transport_fw to receive the request and subsequently calls nb_transport_bw to send the response. The code fragment below is just an outline, but it does show the main idea that non-blocking transport allows timing points to be modeled by having multiple method calls in both directions (as opposed to a single method call in one direction for b_transport):

class target extends vmm_xactor;
`vmm_typename(target)

vmm_tlm_nb_transport_export #(target, vmm_tlm_generic_payload) m_nb_export;

// Implementation of nb_transport method
virtual function vmm_tlm::sync_e nb_transport_fw(
int id=-1, vmm_tlm_generic_payload trans,
ref vmm_tlm::phase_e ph, ref int delay);

-> ev;
return vmm_tlm::TLM_ACCEPTED;
endfunction : nb_transport_fw

// Process to send response by calling nb_transport on backward path
virtual task run_ph;
forever  begin: loop
vmm_tlm::phase_e phase = vmm_tlm::BEGIN_RESP;
@(ev);
tx.m_response_status = vmm_tlm_generic_payload::TLM_OK_RESPONSE;
status = m_nb_export.nb_transport_bw(tx, phase, delay);
end
endtask: run_ph

Now for the main point. We can use tlm_connect to bind the two components together, despite the fact that one uses blocking calls and the other non-blocking calls:

virtual function void build_ph;
m_initiator = new( “m_initiator”, this );
m_target    = new( “m_target”,    this );
endfunction: build_ph

virtual function void connect_ph;

vmm_connect #(.D(vmm_tlm_generic_payload))::tlm_transport_interconnect(
m_initiator.m_b_port, m_target.m_nb_export, vmm_tlm::TLM_NONBLOCKING_EXPORT);

endfunction: connect_ph

That’s all there is to it! Notice that tlm_transport_interconnect is a static method of vmm_connect so its name is prefixed by the scope resolution operator and an instantiation of the vmm_connect parameterized class with the appropriate transaction type, namely the generic payload. The first argument is the port, the second argument the export, and the third argument indicates that it is the export that is non-blocking.
It is also possible to connect a non-blocking initiator to a blocking target: you would simply replace TLM_NONBLOCKING_EXPORT with TLM_NONBLOCKING_PORT. The objective of this post has been to show that VMM has all the bases covered when it comes to connecting together transaction-level ports.

Posted in Interoperability, Reuse, SystemC/C/C++, Transaction Level Modeling (TLM) | Comments Off

TLM and VMM – What is it all for?

Posted by John Aynsley on 18th August 2010

John Aynsley, CTO, Doulos

Having discussed some of the technical details of the implementation of the TLM-2 standard in VMM 1.2 in previous posts, it is time to stand back and ask what it is all for, especially considering that VMM must now co-exist alongside UVM in some projects. Fortunately, using the OSCI TLM standard as a basis for communication takes us a long way down the road toward interoperability, both between VMM and UVM and between VMM and SystemC.

We have seen that VMM 1.2 now supports the concept of ports and exports borrowed from SystemC and the closely related concept of sockets from the TLM-2 standard. Armed with these new concepts, VMM now offers two alternative communication mechanisms: communication between a producer and a consumer through an intermediate channel (the vmm_channel), and communication using direct function calls from producer to consumer (and vice versa) through ports and sockets. So what? Well, the benefits of direct communication were reviewed in an earlier post, but in summary, the simplicity of direct communication can speed up simulation by removing the number of context switches between processes and can provide an easy-to-follow completion model for knowing when a transaction is over. VMM users now have the choice between channel-based communication and direct communication. Channel-based communication works just fine, and may be preferred in native VMM environments. Direct communication is closer to the communication model used in UVM and in SystemC TLM-2.0, so may be preferred when working in a mixed environment, such as when integrating VMM and UVM components or when driving SystemC models from a VMM test bench.

We have also seen that VMM 1.2 supports the generic payload and extension mechanism from the SystemC TLM-2.0 standard. Frankly, this addition is unlikely to be of much interest in native VMM environments, but could be critical when it comes to including SystemC reference models in a VMM test bench. Say you have an existing SystemC reference model written to the TLM-2.0 standard, and you want to drive it from a VMM test bench. The new features in VMM 1.2 would allow you to construct a transaction within the VMM environment that has precisely the attributes expected by the TLM-2.0 standard generic payload, and then to pass that transaction over the fence from SystemVerilog to SystemC. It is possible to code the SystemVerilog-to-SystemC interface yourself using the DPI (for details see http://www.doulos.com/knowhow/sysverilog/DVCon10_dpi_paper) or to use the TLI (Transaction Level Interface) provided by Synopsys. I will say more about the TLI in a later post.

I have heard some VMM users say that they like the idea of being able to use the industry standard blocking transaction-level interface in VMM. Indeed, given the relatively small size of the overall hardware verification community and the cost of maintaining multiple standards, the sharing of ideas between standards in this way has to be a good thing. The early adopter release of UVM, the Universal Verification Methodology from Accellera, uses communication based on the SystemC TLM-1 standard. Even as I write this post, Accellera are considering the best way to incorporate the TLM-2-style interfaces as used in VMM into UVM, which should help make transaction-level communication between the two methodologies a little easier.

Posted in Reuse, SystemC/C/C++, Transaction Level Modeling (TLM) | Comments Off

TLM Sockets in VMM 1.2

Posted by John Aynsley on 12th August 2010

John Aynsley, CTO, Doulos

Having introduced both the blocking and the non-blocking transport interfaces in previous blog posts, it’s now time to look at TLM sockets in VMM 1.2.

In the SystemC TLM-2.0 standard, sockets are a mechanism that simplifies the instantiation and binding of multiple ports and exports for the various standard transaction-level interfaces by encapsulating several interfaces in a single object, the so-called socket. One initiator socket is bound to one target socket using one bind operator, and it is then possible to call all of the standard TLM-2.0 interface methods through that one pair of sockets. Moreover the socket has a BUSWIDTH parameter which represents the width of the data word transferred over the bus on each beat and which prevents sockets of different widths being inadvertently connected together.

Because VMM supports neither the full set of interfaces from the TLM-2.0 standard, nor the functionality of specified bus widths, nor the interoperability achieved by mandating the use of standard socket types, the value of sockets is considerably reduced in VMM compared to the SystemC TLM-2.0 standard. Nonetheless, the TLM sockets in VMM do allow both blocking and non-blocking transport method calls to be made through a single pair of sockets.

Let’s look at an example:

class initiator extends vmm_xactor;
`vmm_typename(initiator)
vmm_tlm_initiator_socket #(initiator, vmm_tlm_generic_payload) m_socket;

begin

m_socket.b_transport(tx, delay);

end

begin

status = m_socket.nb_transport_fw(tx, phase, delay);

end

virtual function vmm_tlm::sync_e nb_transport_bw( int id=-1,
vmm_tlm_generic_payload trans, ref vmm_tlm::phase_e ph, ref int delay);

endfunction : nb_transport_bw

endclass: initiator


As you can see above, the vmm_tlm_initiator_socket allows both b_transport and nb_transport_fw calls to be made through a single socket, as well as being able to accept incoming nb_transport_bw calls.

On the target side, the vmm_tlm_target_socket accepts incoming calls to both b_transport and nb_transport_fw as well as allowing outgoing calls to nb_transport_bw:


class target extends vmm_xactor;
`vmm_typename(target)
vmm_tlm_target_socket #(target, vmm_tlm_generic_payload) m_socket;

task b_transport(int id = -1, vmm_tlm_generic_payload trans, ref int delay);

endtask : b_transport

virtual function vmm_tlm::sync_e nb_transport_fw( int id=-1,
vmm_tlm_generic_payload trans, ref vmm_tlm::phase_e ph, ref int delay);

endfunction : nb_transport_fw


begin

status = m_socket.nb_transport_bw(tx, phase, delay);

end

endclass: target


Finally, at the top level, there is just a single pair of sockets to bind:

class tb_env extends vmm_group;
`vmm_typename(tb_env)
initiator  m_initiator;
target     m_target;

virtual function void build_ph;
m_initiator = new( “m_initiator”, this );
m_target    = new( “m_target”,    this );
endfunction: build_ph

virtual function void connect_ph;

m_initiator.m_socket.tlm_bind( m_target.m_socket );

endfunction: connect_ph

endclass: tb_env


That’s all there is to it!

The SystemC TLM-2.0 standard provides so-called convenient sockets, some of which can automatically convert incoming calls from b_transport to nb_transport and vice-versa. The VMM implementation achieves a similar result using the vmm_connect utility, which I will describe in a future post.

Posted in SystemC/C/C++, Transaction Level Modeling (TLM) | 1 Comment »

Why do the SystemC guys use TLM-2.0?

Posted by John Aynsley on 29th April 2010

JohnAynsley John Aynsley, CTO, Doulos

Since this is the Verification Martial Arts blog, I have focused so far on features of VMM 1.2 itself. But some of you may be wondering why all the fuss about TLM-2.0 anyway? Why is TLM-2.0 used in the SystemC domain?

I guess I should first give a quick summary of how and why SystemC is used. That’s easy. SystemC is a C++ class library with an open-source implementation, and it is used as “glue” to stick together component models when building system-level simulations or software virtual platforms (explained below). SystemC has Verilog-like features such as modules, ports, processes, events, time, and concurrency, so it is conceivable that SystemC could be used in place of an HDL. Indeed, hardware synthesis from SystemC is a fast-growing area. However, the primary use case for SystemC today is to create wrappers for existing behavioral models, which could be plain C/C++, in order to bring them into a concurrent simulation environment.

A software virtual platform is a software model of a hardware platform used for application software development. Today, such platforms typically include multiple processor cores, on-chip busses, memories, and a range of digital and analog hardware peripherals. The virtual platform would typically include an instruction set simulator for each processor core, and transaction-level models for the various busses, memories and peripherals, many of which will be intellectual property (IP) reused from previous projects or bought in from an external supplier.

The SystemC TLM-2.0 standard is targeted at the integration of transaction-level component models around an on-chip communication mechanism, specifically a memory-mapped bus. When you gather component models from multiple sources you need them to play together, but at the transaction level, using SystemC alone is insufficient to ensure interoperability. There are just too many degrees of freedom when writing a SystemC communication wrapper to ensure that two models will talk to each other off-the-shelf. TLM-2.0 provides a standardized modeling interface between transaction-level models of components that communicate over a memory-mapped bus, such that any two TLM-2.0-compliant models can be made to talk to each other.

In order to fulfil its purpose, the primary focus of the SystemC TLM-2.0 standard is on speed and interoperability. Speed means being able to execute application software at as close to full speed as possible and TLM-2.0 sets very aggressive simulation performance goals in this respect. Interoperability means being able to integrate models from different sources with a minimum of engineering effort, and in the case of integrating models that use different bus protocols, to do so without sacrificing any simulation speed.

So finally back to VMM. It turns out that the specific features of TLM-2.0 used to achieve speed and interoperability do not exactly translate into the SystemVerilog verification environment, where the speed goals are less aggressive and there is not such a singular focus on memory-mapped bus modeling. But, as I described in a previous post on this blog, there are still significant benefits to be gained from using a standard transaction-level interface within VMM, both for its intrinsic benefits and in particular when it comes to interacting with virtual platforms that exploit the TLM-2.0 standard.

Posted in Interoperability, Optimization/Performance, SystemC/C/C++, Transaction Level Modeling (TLM) | 2 Comments »

Analysis Ports in VMM 1.2

Posted by John Aynsley on 3rd March 2010

JohnAynsley

John Aynsley, CTO, Doulos

Analysis ports are another feature from the SystemC TLM-2.0 standard that has been incorporated into VMM 1.2. Analysis ports provide a mechanism for distributing transactions to passive components in a verification environment, such as checkers and scoreboards.

Analysis ports and exports are a variant on the TLM ports and exports that I have discussed in previous blog posts. The main difference between analysis ports and regular ports is that a single analysis port can be bound to multiple exports, in which case the same transaction is sent to each and every export or “subscriber” or “observer” connected to the analysis port. The terms subscriber and observer are used interchangeably in the VMM documentation.

Let us take a look at an example:

class my_tx extends vmm_data;  // User-defined transaction class

class transactor extends vmm_xactor;
vmm_tlm_analysis_port #(transactor, my_tx) m_ap;   // The analysis port

virtual task main;
my_tx tx;

m_ap.write(tx);

The transactor above sends a transaction tx out through an analysis port m_ap.

The type of the analysis port is parameterized with the type of the transactor and of the transaction my_tx. The call to write sends the transaction to any object that has registered itself with the analysis port. There could be zero, one, or many such observers registered with the analysis port.

To continue the example, let us look at one observer:

class observer extends vmm_object;
vmm_tlm_analysis_export #(observer, my_tx) m_export;
function new (string inst, vmm_object parent = null);

m_export = new(this, “m_export”);

function void write(int id, my_tx tx);

The observer has an instance of an analysis export and must implement the write method that the export will provide to the transactors. Note that the observer extends vmm_object. Since an observer is passive, it need not extend vmm_xactor.

The analysis port may be bound to any number of observers in the surrounding environment:

class tb_env extends vmm_group;
transactor  m_transactor;
observer    m_observer_1;
another     m_observer_2;
yet_another m_observer_3;
virtual function void build_ph;
m_transactor = new( “m_transactor”, this );
m_observer   = new( “m_observer”,   this );

endfunction
virtual function void connect_ph;
m_transactor.m_ap.tlm_bind( m_observer_1.m_export );
m_transactor.m_ap.tlm_bind( m_observer_2.m_export );
m_transactor.m_ap.tlm_bind( m_observer_3.m_export );

Note the use of the predefined phase methods from VMM 1.2. Transactors are created during the build phase, and ports are connected during the connect phase.

Finally, let us compare analysis ports with VMM callbacks:

m_ap.write(tx);
versus
`vmm_callback(callback_facade, write(tx));

The effect is very similar, but there are differences. Unlike VMM callbacks, the name of the method called through an analysis port is fixed at write. A VMM callback method is permitted to modify the transaction object, whereas a transaction sent through an analysis port cannot be modified. When multiple callbacks are registered, the prepend_callback and append_callback methods allow you to determine the order in which the callbacks are made, whereas you have no control over the order in which write is called for multiple observers bound to an analysis port. Because of these differences, only VMM callbacks are appropriate for modifying the behavior of transactors. Analysis ports are only appropriate for sending transactions to passive components that will not attempt to modify the transaction object. On the other hand, that in itself is the feature and strength of analysis ports; they are only for analysis.

It can make sense to combine a VMM callback with an analysis port in the same transactor, using the callback to inject an error and the analysis port to send the modified transaction to a scoreboard, for example:

`vmm_callback(callback_facade, inject_error(tx));
m_ap.write(tx);

In this situation, the VMM recommendation is to make the analysis call after the callback, as shown here.

Posted in Communication, Reuse, SystemC/C/C++, Transaction Level Modeling (TLM), VMM infrastructure | Comments Off

The Curious World of Ports and Exports in VMM 1.2

Posted by John Aynsley on 4th February 2010

JohnAynsley

John Aynsley, CTO, Doulos

In a previous post I discussed the new blocking transport interface of VMM 1.2, and described how a producer can call the b_transport method implemented by a consumer. In this post, I will describe how to connect the producer to the consumer using the new features of VMM 1.2.

The new features discussed here were inspired by the SystemC TLM-2.0 standard. In SystemC, two modules wishing to communicate get connected using so-called “ports” and “exports”. Although the underlying concept is both elegant and powerful, the terminology “port” and “export” often seems to cause confusion. Since this is now part of VMM 1.2, I will explain. Let us consider a simple example of a producer calling the b_transport method implemented in a consumer.

class my_tx extends vmm_data; // User-defined transaction class

class producer extends vmm_xactor;
vmm_tlm_b_transport_port #(producer, my_tx) m_port;
my_tx tx;

m_port.b_transport(tx, delay);

class consumer extends vmm_xactor;
vmm_tlm_b_transport_export #(consumer, my_tx) m_export;
task b_transport(int id = -1, my_tx trans, ref int delay);

class my_env extends vmm_group;
producer m_producer;
consumer m_consumer;

virtual function void connect_ph;
m_producer.m_port.tlm_bind( m_consumer.m_export );
endfunction

What is happening here is that the producer is calling b_transport through a port, the consumer is providing an implementation of b_transport using an export, and the top-level environment is connecting (or “binding”) the port to the export. The tlm_bind method is creating the link between the port and the export such that when the producer calls b_transport, it is the implementation of b_transport within the consumer that actually gets called.

Both the port and the export declarations are parameterized with the type of the transactor (producer/consumer) and the type of the transaction (my_tx). You may notice that the implementation of b_transport has an extra int id argument. This can be used to distinguish between transactions arriving from different producers. I will discuss this in my next blog post.

The purpose of ports and exports is to provide a structured way of making method calls between VMM transactors (or SystemC modules) such that the dependencies between each transactor and its environment can be minimized. To call b_transport the code within the producer only need refer to the port and has no direct dependencies on any code outside that transactor. Similarly, to call the b_transport method implemented within the consumer, the environment only need refer to the export. It is only when the port and export are connected within the connect_ph method of the environment that a specific dependency is established between the producer and consumer transactors.

What about those terms “port” and “export”? The term port was originally borrowed from VHDL and Verilog. In SystemC, a port allows an interface method call to be made up-and-out-of a module. When SystemC was enhanced to add the mirror image construct that allows an interface method call to be made down-and-into a module the term “export” was chosen because an export provides or “exports” an interface, whereas a port “imports” an interface.

If we could re-write history, I guess we might have chosen the term “import” instead of “port”. Perhaps that would have caused less confusion. Or maybe not!

Posted in SystemC/C/C++, Transaction Level Modeling (TLM) | 1 Comment »

Transaction Level Modeling – Value add in different languages.

Posted by Nasib Naser on 14th December 2009

Nasib_NaserNasib Naser, PhD

Sr. Staff Corporate Applications Engineer – Synopsys

One of the driving factors of creating SystemVerilog is to raise the design verification abstraction level. The reason for such a move is described in the SV LRM Abstract. It says: “A set of extensions to the IEEE 1364-2001 Verilog Hardware Description Language to aid in the creation and verification of abstract architectural level models.” So why and how? The “Why” is obvious. A number of reasons come to mind:

  1. Faster development and simulation to enable reaching design and verification goals sooner than later.
  2. Achieve early closure on architectural decisions without early commitment to implementation details.
  3. Enable running “some” software within the complete system context.
  4. Create an environment in which verification methodologies could be developed that creates true verification IP re-usability and models interoperability.

This blog will discuss the methodology behind the “How.” The technology will be explained in subsequent blogs. Up until vmm 1.2 was released Transaction based models were created by utilizing VMM constructs such as vmm_channel(), vmm_xactor(), and vmm_data() . With all VMM strengths this use model succeeded only on in-house designs and didn’t gain wide modeling adoption. The TLM methodology built into VMM lacked common practices to enable interoperability – emphasis on common practice.

Meanwhile, driven by users, the Open SystemC Initiative aka OSCI TLM community managed to create a standard on which models could be developed for re-use and interoperability. Without dwelling in the past I’d like to give a brief history on the evolution that led to the TLM standard. In the beginning there was C, then C++. For obvious reasons these widely known software languages were used to develop in-house system level models for doing high level performance and architectural analysis. The use model was very limited as the simulation behavior was very far from the actual hardware. It lacks concurrency and timing. C++ extensions augmented with a “proof of concept” simulator was created and called SystemC that enable modeling these hardware behaviors in C++, and more. That worked very well. Failing to replace Verilog and vhdl for design and verification SystemC found its niche use model in the architectural modeling domain. At that point architects using SystemC started to demand a standard that enables interoperability for fast platform composition, ease of use, and re-usability. Hence, the OSCI SystemC Transaction Level Modeling 1.0 and later 2.0 standards were created.

So why re-invent the wheel when it comes to SystemVerilog TLM? And why not adopt a powerful and robust verification methodology such as VMM standard to enable seamless integration between SystemC and SystemVerilog? That’s why features described in the OSCI TLM standard found its way into the SystemVerilog/VMM world. These features are available in the newly released VMM 1.2. Subsequent blogs I will explain these features and the value add they bring into a true IP re-use and interoperable verification methodologies.

Posted in Interoperability, Reuse, SystemC/C/C++, Transaction Level Modeling (TLM) | Comments Off

Blocking Transport Communication in VMM 1.2

Posted by John Aynsley on 10th December 2009

image John Aynsley, CTO, Doulos

One of the new features in VMM 1.2 is the blocking transport interface, borrowed from the SystemC TLM-2.0 standard. This interface provides an alternative to the using the put and get methods of the vmm_channel class when communicating between a producer and consumer. There are a couple of reasons why you might consider using the blocking transport interface in VMM: perhaps you are trying to interface to a SystemC reference model, or perhaps you want to write a transactor that has very clean semantics when it comes to determining the start and end of a transaction. In either case, the new blocking transport interface can help.

A blocking transport call is a method call that carries with it a transaction object and is expected not to return until the transaction is complete. The status of the transaction, that is, whether the transaction succeeded or failed, is expected to be carried within the transaction object itself. You call blocking transport as follows:

class my_tx extends vmm_data; // A user-defined transaction class

enum {OKAY, FAIL} status; // Status flag embedded in the transaction itself
endclass

my_tx tx;
int delay;

$cast(tx, randomized_tx.copy()); // Create and randomize a transaction object

m_port.b_transport(tx, delay);

if( tx.m_status != OKAY ) // Check the response status
`vmm_warning(log, “Transaction failed”);

Since this is SystemVerilog, the transaction object itself is passed by reference. The delay argument instructs the recipient of the transaction to process the transaction after the given delay has elapsed, and can be set by both the caller of and the implementation of the b_transport method.

The blocking transport method needs to be implemented by the transactor that will receive or consume the transaction:

task b_transport(int id = -1, my_tx tx, ref int delay);

// Process transaction

// Pause for given delay and then reset the delay argument
#(delay);
delay = 0;

// Set the response status in the transaction object
tx.m_status = OKAY;
endtask : b_transport

By definition, blocking transport “blocks” until the transaction has been fully processed. It is coded as a SystemVerilog task so that it is allowed to execute timing controls such as the #(delay) in this example. The task is not obliged to suspend for the given delay in this manner; it could have simply returned leaving the delay without modification, or even have increased the value of the delay, leaving it for the caller to realize the delay later. The task is obliged to set the response status flag within the transaction object before returning, and the caller must check the response status on return.

One significant thing that is happening here is that communication between a producer and a consumer (or in TLM-2.0 jargon, an initiator and a target) is being accomplished without having any intervening channel to buffer the transactions. The b_transport method is called by the producer, provided by the consumer, and only returns when the transaction is complete. The advantage of not having an intervening channel is that it can help increase execution speed in the context of a very fast simulation model. The disadvantage is that it is not possible to have multiple transactions in progress given only a single execution thread in the initiator; therefore, it is a good idea to add a semaphore in the implementation of the b_transport method in the target transactor

class target_xactor extends vmm_xactor;

local semaphore m_sem = new(1);

task b_transport(int id = -1, my_tx tx, ref int delay);
m_sem.get(1);
// Process transaction

m_sem.put(1);
endtask : b_transport

This is not the whole story, because we also need to explain how to connect the producer to the consumer. Look out for future blog posts.

Posted in Communication, Reuse, SystemC/C/C++, Transaction Level Modeling (TLM) | 2 Comments »

What Has TLM-2.0 Got To Do With It?

Posted by John Aynsley on 17th November 2009

JohnAynsley

John Aynsley, CTO, Doulos

You may have noticed that the public release of VMM 1.2 is just around the corner, and with this new version of VMM comes the introduction of features inspired by the SystemC TLM-2.0 standard.

Excuse me! TLM-2.0? What? Why do we need features from SystemC in VMM?

I will set out to answer that question fully in a series of blog posts over the coming months. But first off I will remark that the idea is not so strange. After all, VMM has always been transaction-level (with a small ‘t’ and ‘I’). Communication within a VMM verification environment exploits transaction-level modeling for speed and productivity, because “TLM” is about abstracting the model of communication used in a simulation. If we can adopt a common standard for transaction-level modeling across both SystemC and SystemVerilog, that has to be a good thing for everyone. It is evident that the design and verification community demands more than one language standard (witness VHDL, SystemVerilog, C/C++, and SystemC). Each individual language standards has progressed over time by borrowing the best features from the others. Having VMM borrow features from SystemC makes it easier to learn and work with both standards.

The other natural link between VMM and SystemC is that mixed-language simulation environments and C/C++ reference models are not unusual. Virtual platform models, as used for software development and architectural exploration, are growing in importance, and the SystemC TLM-2.0 standard is used to achieve interoperability between the components of a virtual platform model. If a constrained random VMM environment is to be used with a reference model that consists of a virtual platform adhering to the SystemC TLM-2.0 standard, then having TLM-2.0 support within VMM promises to make life easier for the VMM programmer.

Besides interoperability, the other main objective of the SystemC TLM-2.0 standard is simulation speed. The combination of speed and interoperability is achieved by the technical details of the ways in which transactions are passed between components. Fortunately, those technical details are a good fit with the way communication has always worked in VMM. In particular, both VMM and TLM-2.0 support the idea that each transaction has a finite lifetime with a well-defined time-of-birth and time-of-death.

The SystemC TLM-2.0 standard is based on C++. Unfortunately, not all C++ coding idioms translate naturally into SystemVerilog, so the transaction-level communication in VMM 1.2 is “inspired by” the TLM-2.0 standard rather than being a literal rendition of it.

So what are these new features? If you are already a SystemC user you may recognize ports and exports, borrowed directly from the SystemC standard, and analysis ports, transport interfaces, sockets and the generic payload, borrowed from the TLM-2.0 standard. I will explain how VMM is able to exploit each of these features in future blog posts, so watch this space…

Posted in Interoperability, Reuse, SystemC/C/C++, Transaction Level Modeling (TLM) | Comments Off

How to connect your SystemC Reference Models to your verification VMM based framework

Posted by Shankar Hemmady on 17th August 2009

Nasib_Naser

Nasib Naser, Phd, CAE, Synopsys

In this blog I will discuss the Use Model demonstrated in Figure 1 where a VMM layered testbench is used to verify an RTL DUT against a SystemC transaction level model. SystemVerilog allows for the creation of a reusable layered testbench architectures. The VMM methodology provides the basis for such a layered architecture. With a layered approach, transaction-level reference models can be easily integrated at the appropriate level to provide self-checking functions. In this Use Model the VMM Function layer is communicating with SystemC model using the TLI mechanism to perform read/write transactions, and using the same testbench scenarios the VMM command layer is driving the DUT at pin level.

clip_image002

Figure 1 – VMM driving TLM and RTL with checking

Synopsys’ VCS functional verification solution addresses the challenge of this use model with its SystemC-SystemVerilog Transaction-Level Interface (TLI). Using TLI SystemC interface methods can be invoked in SystemVerilog and vice versa. The **value add** for using TLI is that the SystemVerilog DPI based communication code that synchronizes both domains is automatically generated.

Let’s take a look at the various code components in SystemC and SystemVerilog based on the VMM methodology that enables such a verification use model. In the following example we define the read and write transactions as SC Interface methods.

class Buf_if: virtual public sc_interface {
public:

// do the pure virtual function read()/write() declarations here
virtual void read(unsigned int addr, unsigned int* data) = 0;

virtual void write(unsigned int addr, unsigned int data) = 0;
};

Following code shows VMM Transactor invoking SystemC transactions read and write at function layer. VMM transactor tb_mast is communicating to SystemC TLM using vmm channel tb_mast_out_ch1 and with the RTL model using the vmm channel tb_mast_out_ch2 channel, as shown in the following code:

class tb_master extends vmm_xactor;
virtual tb_if.master ifc;
tb_data_channel tb_master_in_ch;
tb_data_channel
tb_master_out_ch1;
tb_data_channel
tb_master_out_ch2;

extern virtual task main();
endclass: tb_master

task tb_master::main();
tb_data tr, tr_out;
super.main();
forever begin
.
..
// Send the Instruction to SC Reference Model
tb_master_out_ch2.put(tr_out);
// Send the Instruction to RTL
tb_mast_out_ch1.put(tr_out);
end
endtask: main

The following code shows VMM reference Transactors calling the SystemC transaction functions via the adaptor alu_tl_if_adpt_vlog which was automatically generated by VCS TLI.

class tb_ref extends vmm_xactor;

tb_data_channel     tb_ref_in_ch;

alu_tl_if_adpt_vlog alu_tl_if_adpt_vlog_inst0;


extern function new (string instance,
integer stream_id = -1,

tb_data_channel tb_ref_in_ch = null);

extern virtual task main();

endclass: tb_ref

task tb_ref::main();

super.main();

forever begin

case(tr_out.tb_data_type)

SA_SB_OP_GO : begin

alu_tl_if_adpt_vlog_inst0.write(addrA,a);

alu_tl_if_adpt_vlog_inst0.write(addrB,b);

alu_tl_if_adpt_vlog_inst0.write(addrOP,op);

alu_tl_if_adpt_vlog_inst0.read(addrOut,d);

tr_out.data_out = d;
end

endcase

end

endtask

This VCS TLI use model provides a complete and easy way to integrating blocking and non-blocking SystemC reference models into a VMM based multi-layer verification environment.

Posted in SystemC/C/C++, SystemVerilog, Transaction Level Modeling (TLM), Tutorial, VMM | Comments Off

How to connect your SystemC reference model to your verification framework

Posted by Janick Bergeron on 8th July 2009

Nasib Naser, Phd, CAE, Synopsys

Architects and designers have many reasons to start using the SystemC language to describe their high level specifications for their target System-on-Chip (SoC). In this blog I will not discuss the “why” the SystemC selection BUT the “how” to bring these models into the team’s design verification flow.

Mixed abstractions come from the fact that designers often develop models at the transaction level to capture the correct architecture and analyze the system performance and do so fairly early in the design cycle. Various components of a SoC developed with high level languages such as C, C++, SystemC, and SystemVerilog are increasingly in demand and for obvious reasons. They are faster to write and faster to simulate. High level reference models became increasingly important in verifying the implementation details at the RTL level.

Although SystemVerilog provides different methods (PLI, VPI, DPI, etc) to support communications between SystemVerilog and C/C++ domains, it is not so straight forward for SystemC interface methods. One important reason is that these SystemC methods can be “blocking”, i.e. these methods can “consume” time. And these “blocking” SystemC methods can return value as well. Users should build a very elaborate mechanism to maintain synchronization between the simulations running in the SystemVerilog and the SystemC domains.

Synopsys’ VCS functional verification solution addresses the challenge of this use model with its SystemC-SystemVerilog Transaction-Level Interface (TLI). With TLI, VCS automatically generates adapters to be instantiated in each domain to support SystemVerilog block calls of SystemC methods, or vice versa. These TLI adapters take care of the synchronization between both domains.

To demonstrate the ease of use of this unique interface we start by identifying the SystemC interface methods that SystemVerilog require accessibility to. In the following example we define Read and Write transactions as SC Interface methods as such:

#include<systemc.h>
class Mem_if : virtual public sc_interface {
public :

   //do the pure virtual function declaration here
  
virtual void rd_data(int addr, int &data)=0;
  
virtual void wr_data(int addr, int data)=0;
};

Manually we create an interface configuration file that declares the methods required for the interface. These methods are declared in a file called Mem_if.h. The content of this configuration file is as follows:

interface Mem_if
direction sv_calls_sc
verilog_adapter Mem_if_adapt_vlog
systemc_adapter Mem_if_adapt_sc

#include "Mem_if.h"

task rd_data
input int addVal
inout& int dataVal

task wr_data
input int addVal
input int dataVal

#endif
};

VCS uses this configuration file to generate the necessary SystemC and SystemVerilog code that enables complete synchronization. The command line is as follows:

%syscan -idf Mem_if.idf

This operation creates the following helper files:

Mem_if_adapt_sc.cpp
Mem_if_adapt_sc.h
Mem_if_adapt_vlog.sv

The helper file Mem_if_adapt_vlog.sv contains a SystemVerilog Interface called Mem_if_adapt_vlog which declares the following tasks:

task wr_data(input int addVal, input int dataVal);
task rd_data(input int addVal, inout int dataVal);

These tasks could then be wrapped and used in the SystemVerilog testbench to access SystemC methods as demonstrated in the following code:

module testbench;
reg clk;
int data;
int cnt;

// Instantiate the helper interface
Mem_if_adapt_vlog #(0) mem_if_adapt_vlog_inst();

// THE CODE BELOW IS WHERE ALL THE SC TLI FUNCTIONS ARE CALLED.
// VERILOG TASKS ARE WRITTEN AS A WRAPPER FOR READABILITY.
// THESE WRAPPER TASKS ARE INSTANTIATED IN THE VERILOG CODE.

// Calling SC TLI function **Write Data**
task
sv_wr_data(input int addr, input int data);
  
mem_if_adapt_vlog_inst.wr_data(addr,data);
endtask

// Calling SC TLI function **Read Data**
task
sv_rd_data(input int addr, output int data);
  
mem_if_adapt_vlog_inst.rd_data(addr,data);
endtask

. . .

// Use the wrapper code
always @(posedge clk)
begin
   if(cnt < 100)
   begin
      #8
sv_wr_data(cnt,cnt+100);
     
cnt = cnt+1;
   end
end

always @(posedge clk)
begin
   if(cnt < 100)
   begin
      #3
sv_rd_data(cnt-1,data);
  
end
end

endmodule

Posted in SystemC/C/C++, SystemVerilog, Tutorial, VMM | 1 Comment »

00a7b3860da188b92ea3cdfcde2fd47dPPPPPPPPPPPPPPPPPP