20
System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability 1 System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability Authors Parag Goel [[email protected] ] Pushkar Naik [[email protected] ]

Sv Ovm Paper Part1

Embed Size (px)

DESCRIPTION

system verilog OVM guide

Citation preview

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    1

    System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    Authors Parag Goel [[email protected]]

    Pushkar Naik [[email protected]]

    mailto:[email protected]:[email protected]

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    2

    Abstract Verification has been becoming a nightmare for engineers with the increasing requirements and complexity of the design. Mitigating the complexity of a verification environment with the increasing complexity of design verification can be re-defined as a CHALLENGE. System Verilog along with its library of classes OVM, provides a platform to face this CHALLENGE. This paper explains how, in our endeavor to accomplish an ideal verification platform for our designs using System Verilog and a standard methodology(OVM) plus some in-house ideas over it, helped us to make a more practical and easy to use verification environment. The challenges spanned right from configuring the components, injecting the transactions to create various test scenarios, phasing of the test cases till the end of report generation etc. This paper also explains how SV & OVM has simplified a whole lot in controlling the messaging policy, sequences & sequencers layering, OOPs data patterning to fit certain environment architecture requirements, barrier mechanism to overcome OVM phasing limitations and ready-made harness system for the sub-system integration, making things simpler & organized. It also explains how the addition of a thin layer between the OVM Methodology classes and our projects base classes helped us in shielding our projects from any changes in upcoming OVM releases as well as served to provide a place holder for any additional functionality in our base classes, without even touching the OVM source code as such. Towards the end, some points to ponder have been summarized based on our experience with OVM and some enhancements in Questasim / OVM are suggested.

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    3

    Table of Contents

    Contents

    1 Introduction -------------------------------------------------------------------------------------------------------------------------------- 4

    2 OOPs Design Patterns (Singleton Instantiating One Object) --------------------------------------------------------- 4

    3 Use of Parameterized Interface(s) in a Package ------------------------------------------------------------------------------ 7

    4 Harness- a Complete Sub-system definition ----------------------------------------------------------------------------------- 8

    5 Sequencer Layering -------------------------------------------------------------------------------------------------------------------- 13

    6 Single Class / Multiple Analysis ports --------------------------------------------------------------------------------------------- 15

    7 SV world to C world - Host Communication ---------------------------------------------------------------------------------- 18

    Code References Code 1 Example for Singleton Statistics collector ........................................................................................ 5 Code 2 Example for Singleton memory implementation ............................................................................... 6 Code 3 Example for Singleton memory usage ............................................................................................. 7 Code 4 DUT definition ................................................................................................................................. 10 Code 5 SVTB Interfaces definition .............................................................................................................. 10 Code 6 Virtual Interface packages .............................................................................................................. 10 Code 7 Connection module - AXI ............................................................................................................... 11 Code 8 Connection module - USB .............................................................................................................. 12 Code 9 Testbench Top ................................................................................................................................ 12 Code 10 Monitors to be connected to score-board ..................................................................................... 16 Code 11 Agent code showing monitor & scoreboard connection ............................................................... 16 Code 12 Score-board showing implementation .......................................................................................... 17

    List of Figures Figure 1 Singleton pattern Statistics Collector ........................................................................................... 5 Figure 2 Singleton Pattern Memory Modelling & Sharing .......................................................................... 6 Figure 3 Parameterized Interface(s) in a package ........................................................................................ 8 Figure 4 Verification Setup Requirement ...................................................................................................... 9 Figure 5 Typical Setup Todays Scenario .................................................................................................. 9 Figure 6 Harness The Solution ................................................................................................................ 10 Figure 7 Completely integrated testbench Harness Approach ................................................................ 11 Figure 8 Sequence layering OVM recommended way ............................................................................ 13 Figure 9 Sequence Layering Using Sequencer layering ......................................................................... 14 Figure 10 Analysis FIFO connection model monitor & score-board ........................................................ 15 Figure 11 Host Communication module-level setup ................................................................................ 19 Figure 12 Host communication module/SoC setup ................................................................................. 20

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    4

    1 Introduction

    Seventy percent of project time is consumed in verification and still there are Bug(s) in the design that are revealed after tape-out or at the customer end, that raises question(s) on the ability & the sincerity of the verification engineer and overall credibility of the organization as such. But the real question that needs to be raised is Do we have enough technology available to create all possible stimuli to the DUT and gauge the amount of verification performed so far, quantitatively, in order to confidently say that the DUT has been satisfactorily verified? Is the verification environment available to the tester, providing him/her, enough flexibility to exercise the required test scenarios without modifying the golden test bench? The Methodology we developed at AMCC tried to answer several such above questions utilizing the OVM/SV combination and some in-house ideas as mentioned before. This paper is broadly divided into the following sub-sections:

    1. System Verilog concepts making environment simpler a. Usage of Design patterns b. Usage of parameterized interface(s) in package(s) c. Concept of harness for sub-system port mapping

    2. Advanced OVM Usage a. Sequence / Sequencer layering b. Single Class / Multiple Analysis Ports Usage c. SV to C world host communication

    3. Work done to overcome OVM limitations a. Messaging control in OVCs b. OVM barrier enhanced phasing mechanism

    4. Miscellaneous topics a. Sequence initiation methods comparison in OVM b. Some points to ponder c. Questasim / OVM Enhancements moving forward

    2 OOPs Design Patterns (Singleton Instantiating One Object)

    As per the definition from the book Design Patterns: Elements of Reusable Object-Oriented Software the Singleton design pattern must: Ensure a class only has one instance, and provide a global point of access to it. Usage of this pattern lets you take away control over the object instantiation process from the new operator. This kind of pattern can be used over and above the classes available in the OVM library in cases where one might need to refer one and the same instance of the class across the components and across the hierarchy. To achieve this objective one can use the concept of the Singleton pattern available in OOPs. The two very common applications that can be thought for a VC based on System Verilog are as described below. 1. Statistics Collector class (Refer to Figure 1) There are situations where you require to display

    a summary of information at the end of the simulation which actually helps in deducing the inferences for a given test case. This may broadly consists of ,

    1. The Statistical collection - a summary of injected/collected transactions across the score-board.

    2. Error counters transaction related errors.

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    5

    3. Count of Compares/Mis-Compares of transaction elements etc. can be added to the scoreboard by the user.

    Figure 1 Singleton pattern Statistics Collector

    This block will necessarily be a singleton class that will contain all the properties related to the above mentioned points. These properties shall be populated & updated from several components sitting in the VIP environment, and at the end of simulation it will display the complete information collected in a simple & easy to understand manner. Needless to mention, how OVM also aids in such scenario, by providing certain in-built methods for printing messages uniformly in the report phase etc. Lets understand how it works from the code perspective [Refer to Code 1]:

    Code 1 Example for Singleton Statistics collector

    VIP components populating the properties of a single class.

    Statistics Collector

    Bus Monitor Driver Scoreboard

    class report_handler extends ovm_object;

    //Properties to collect statistics

    int Total_Transfers;

    int Read_Transfers ;

    int Write_Transfers;

    //Register to get built-in methods ready-made

    `ovm_object_utils_begin(report_handler)

    `ovm_field_int(Total_Transfers , OVM_ALL_ON)

    `ovm_field_int(Read_Transfers , OVM_ALL_ON)

    `ovm_field_int(Write_Transfers , OVM_ALL_ON)

    `ovm_object_utils_end

    // object that is created only once

    static *_report_handler single[*];

    function new();

    endfunction

    // method to get object

    static function report_handler get_instance(int id);

    //call the constructor for the first time, if the object has been

    //created already return reference to that object else create new one

    if(!single.exists(id)) begin //{

    // constructor that is called only once

    single[id] = new;

    end //}

    // return the reference to already created object

    return single[id];

    endfunction

    endclass

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    6

    2. Lets take a look at the next application, where one requires modeling a memory with parameterized address and data width which can be used across classes/models, still referring to a single memory array. As shown in the figure below (Refer to Figure 2), a memory is being accessed for reads/writes by the DUT through a Protocol BFM as well as it can be accessed via. a backdoor path accessing the read/write functions written in the memory. [Code : 2,3]

    Figure 2 Singleton Pattern Memory Modelling & Sharing

    Code 2 Example for Singleton memory implementation

    DUT

    Test sequence includes

    initialization + traffic

    Memory model

    Protocol BFM

    Backdoor Path

    class slave_memory #(ADDR_WIDTH = 36,DATA_WIDTH = 128);

    //declaration of assoc array for memory

    bit [DATA_WIDTH-1:0] memory[*];

    static slave_memory#(ADDR_WIDTH,DATA_WIDTH) single[*];

    . . . . . . . . .

    // method to get singleton object

    static function slave_memory #(ADDR_WIDTH,DATA_WIDTH) get_instance(int

    id);

    if(!single.exists(id)) begin //{

    // constructor that is called only once

    single[id] = new;

    end //}

    // return the reference to already created object

    return single[id]; endfunction

    //This task will write the data to a memory using backdoor access.

    task mem_write(bit[ADDR_WIDTH-1:0] address, bit[DATA_WIDTH-1:0] data,

    bit[DATA_WIDTH-1:0] mask = 'hf);

    bit[DATA_WIDTH-1:0] read_data;

    if(memory.exists(address)) begin //{

    mem_read(address, read_data);

    end //}

    memory[address] = ((data & mask) | read_data);

    endtask

    //This task will read the data from a memory using backdoor access

    task mem_read(bit[ADDR_WIDTH-1:0] address, output bit[DATA_WIDTH-1:0]

    data);

    data = memory[address];

    endtask

    endclass : slave_memory

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    7

    Now, lets see what goes into the user side. The steps are as follows:

    Code 3 Example for Singleton memory usage

    To summarize, using this pattern, one can refer to the same instance anywhere within ones environment. The examples discussed were, when one wants to collect the statistics from all the VIP components and display the same as the final report at the end of simulation, and when a single instance of memory is used across environment that is accessed for read/writes by several VIP components. Singleton applies to has_a kind of relationship. Now lets see when the class being treated as Singleton has child classes leading to is_a kind of relationship as well. To achieve the same we can make the constructor protected, so that various subclasses get to inherit the same constructor. But as a general thumb rule, Singleton and subclassing should not be mixed to keep things simpler. Disadvantages:

    1. It creates an object in a given namespace, and the whole idea of namespace defies the OOPs objective to remove the clutter of namespaces

    2. Having only one such global object at a particular time doesnt mean another one cant be created inadvertently in another namespace, giving you some very hard to debug issues.

    3 Use of Parameterized Interface(s) in a Package

    Classes are dynamic in nature while interfaces are static in nature and hence cannot be directly instantiated in a class. So, typically, a real interface instance is created in the top module (or program block) and virtual interface instances are created in various classes where there is a need to access the interface. But we need to connect the various virtual interfaces to the equivalent real interface somewhere. One of the not so elegant ways is to hierarchically pass a virtual interface instance down the layers. OVM suggests a cleaner solution to this, for OVC development. Define a virtual interface package and instantiate a virtual interface for each of the real interface(s) instantiated in the top module or program block[Refer to Figure 5]. Then in the top module or program block, import the virtual interface package and connect the packages virtual interface(s) to the corresponding real interface(s) there. In the various classes where interface access is required, define local instances of the required virtual interface(s). Then import the virtual interface package in each of these classes and connect the local virtual interface instance(s) to the corresponding ones in the imported package.

    //declaring the handle of memory with parameters

    axi_slave_memory #(ADDR_WIDTH,WRITE_DATA_BUS_WIDTH)mem;

    //getting singleton handle to memory

    mem = mem.get_instance(id);

    //memory backdoor read function

    mem.mem_read(address, data);

    //memory backdoor write function

    mem.mem_write(address, data, mask);

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    8

    Figure 3 Parameterized Interface(s) in a package

    But what if these interfaces are parameterized, how do we plan to pass parameters across packages, SV doesnt provide a provision for the same. One way to tackle this is to move the interface to config class and refer from there instead of package. But still packages provide a better global visibility. So, the other solution can be a parameterized class inside the package that contains the parameterized interface instance. Even simpler solution would be to make a package of global defines containing `defines, enums and parameters, and import this package in various other component packages where these are required to refer.

    4 Harness- a Complete Sub-system definition

    A typical verification setup is shown in Figure 4, wherein, various Test Bench Subsystem definitions should be able to take care of the respective interfaces defined in the DUT. An SV interface and associated Class hierarchy together define a Test bench Subsystem. OVM has a well-defined class hierarchy definition to take care of required functions, but the associated interface and its port mapping is still done in the top module (or program block) (Refer to Figure 5). This can make the top messy. Also if a user is integrating this functional entity into a test bench, he/she needs to know the interface of this functional entity in details in order to integrate. This is not what is desired, as the integrator is only interested in integrating the functional entity into rest of test bench, the details of that entitys interface are really to be known by the module owner. This can be avoided if the module owner defines a connection module for that class hierarchy in which all port mappings to the corresponding DUT interface are already taken care of, while this connection module gets simply instantiated in the top by the integrator without knowing the intricacies of that interface. This connection module along-with the related class hierarchy defines a self-sufficient functional entity and is termed a Harness (Refer to Figure 6).

    Connection package (pkg)

    Virtual Interface (vif)

    DUT

    Connection Module

    TESTBENCH

    Real Interface (rif)

    pkg::vif = rif

    Driver

    Monitor

    vif

    vif

    Global defines package

    `defines enums parameters

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    9

    Figure 4 Verification Setup Requirement

    So, as shown in the above requirement setup (Refer to Figure 4), the DUT has two interfaces AXI and USB. Thus we need two TB subsystems that can drive and receive from these two interfaces. The two module owners define the OVM based class hierarchies for these two subsystems as shown below.

    Figure 5 Typical Setup Todays Scenario

    Now, along-with the class hierarchies, its this individual module owners responsibility to define their connection modules as well that port map to the respective DUT interface [Refer to Figure 6].

    TESTBENCH SV INTERFACE

    S

    DUT

    module top(); //USB Port Map .................. .................. .................. //AXI Port map .................. .................. .................. .................. endmodule

    USB Driver

    USB Sequenc

    er

    USB Monitor

    USB Agent

    AXI Driver

    AXI Sequenc

    er

    AXI Monitor

    AXI Agent

    AXI

    US BB

    USB/AXI Class Hierarchies

    DUT

    TEST BENCH

    AXI TB Subsystem

    USB TB Subsystem

    AXI

    USB

    DUT PORTS

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    10

    Figure 6 Harness The Solution

    Now, once the above two subsystems are ready, a third person integrating these two subsystems merely instantiates the respective agents in the environments and instantiates the connection modules in the top without understanding the interfaces of these two subsystems in details as shown below. [Refer to Figure 7][Code: 4, 5, 6, 7, 8, 9]

    Code 4 DUT definition

    Code 5 SVTB Interfaces definition

    Code 6 Virtual Interface packages

    USB Connection

    Module

    USB

    Driver

    USB

    Sequencer

    USB

    Monitor

    USB

    Agent AXI

    Agent

    AXI

    Driver

    AXI

    Sequencer

    AXI

    Monitor

    AXI Connection

    Module

    USB Harness AXI Harness

    interface axi_intf(input clk);

    logic Reset;

    logic [31:0] wrAddr;

    logic [63:0] rdData;

    endinterface

    interface usb_intf (input

    clk);

    logic reset;

    logic txready;

    logic [15:0] datain;

    logic [15:0] dataout;

    logic txvalid;

    endinterface

    module Dut ( clk, reset,

    //USB Intf

    txready,

    datain,

    . . . .

    dataout,

    txvalid,

    //AXI Intf

    Reset,

    wrAddr,

    . . . .

    rdData);

    input clk;

    input reset;

    //USB

    input txready;

    input [15:0]datain;

    output [15:0]dataout;

    output txvalid;

    //AXI

    input Reset;

    input [31:0] wrAddr;

    output[63:0] rdData;

    endmodule

    package axi_vif_pkg;

    virtual axi_intf axi_vif;

    endpackage

    package usb_vif_pkg;

    virtual usb_intf usb_vif;

    endpackage

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    11

    Figure 7 Completely integrated testbench Harness Approach

    Code 7 Connection module - AXI

    USB Connection

    Module

    Top Module

    Test cases

    Test Environment

    USB Driver

    USB Sequencer

    USB Monitor

    USB Agent

    AXI Agent

    AXI Driver

    AXI Sequencer

    AXI Monitor

    AXI Connection

    Module

    import axi_vif_pkg::*;

    module axi_connect(input clk, reset);

    //make real interface instance

    axi_intf axi_rif(clk);

    //port map corresponding dut signals

    always @ (posedge clk) begin

    axi_rif.Reset = reset;

    //DUT Inputs

    top.dut_inst.reset = axi_rif.Reset;

    top.dut_inst.wrAddr = axi_rif. wrAddr;

    //DUT Outputs

    axi_rif.rdData = top.dut_inst.rdData;

    end

    //Map the floating Virtual Interface instance in the

    package to the real interface instance

    initial begin

    axi_vif_pkg::axi_vif = axi_rif;

    end

    endmodule

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    12

    Code 8 Connection module - USB

    Code 9 Testbench Top

    module top();

    bit clk = 0;

    bit reset = 0;

    initial begin

    forever clk = #TP ~clk;

    end

    initial begin

    @ (posedge clk);

    reset = 1b1;

    repeat (5) @ (posedge clk);

    reset = 1b0;

    end

    //instantiate axi connection module

    axi_connect axi_connect_inst(clk, reset);

    //instantiate usb connection module

    usb_connect usb_connect_inst(clk, reset);

    //instantiate dut

    Dut dut_inst;

    endmodule

    import usb_vif_pkg::*;

    module usb_connect(input clk, reset);

    //make real interface instance

    usb_intf usb_rif(clk);

    //port map corresponding dut signals

    always @ (posedge clk) begin

    usb_rif.reset = reset;

    //DUT Inputs

    top.dut_inst.reset = usb_rif.reset;

    top.dut_inst.txready = usb_rif.txready;

    top.dut_inst.datain = usb_rif.datain;

    //DUT Outputs

    usb_rif.dataout = top.dut_inst.dataout;

    usb_rif.txvalid = top.dut_inst.txvalid;

    end

    //Map the floating Virtual Interface instance in

    the package to the real interface instance

    initial begin

    usb_vif_pkg::usb_vif = usb_rif;

    end

    endmodule

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    13

    5 Sequencer Layering

    OVM allows layering of the Sequences, hierarchically, to achieve any complex functionality. But the Sequencer, on which these sequences or hierarchy of sequences is started, expects a given type of ovm_sequence_item derivative, as specified in the Sequencer definition. There can be a requirement in a Verification Environment that few Sequences work on one type of ovm_sequence_item derivative and the output of these Sequences is required to be fed to another type of ovm_sequence_item derivative. Thus a translation is required in between, to convert one type of ovm_sequence_item derivative to another, before the Sequencer and Driver configured to accept second ovm_sequence_item derivative, can consume it. OVM suggested way to handle this would be to arrange these two processing logic in a hierarchical Sequence fashion, as shown below (Refer to Figure 8). But the problem here is that the Translation Sequence not only has to translate between the Trans1 and Trans2, but also has to implement complex arbitration logic to arbitrate between Sequences 1, 2 & 3.

    Figure 8 Sequence layering OVM recommended way

    Here we suggest an OVM reusable approach, where Sequencers Arbitration Logic can be reused in achieving the above objective [Refer to Figure 9].

    Driver

    Sequencer

    Seq1

    Seq2

    Seq3

    Seq6

    Translation Sequence

    Seq4

    Indicates a conversion sequence to convert the Trans1 from Seq1,2,3 to Trans2 as required by Sequencer. Arbitration logic implemented in

    sequence by user

    Transaction (Trans1)

    Transaction (Trans2)

    Sequencer

    arbitration

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    14

    Figure 9 Sequence Layering Using Sequencer layering

    Sequences 1, 2 & 3 as well as Sequencer1 work on ovm_sequence_item derivative type Trans1. Sequencer1s internal arbitration logic (provided by OVM) is used to arbitrate between these Sequences. Now, the output of Sequencer1 needs to be fed to a Translation Sequence as shown. This Translation Sequence is started on Sequencer2 along with Sequences 4 & 5 and all these work on ovm_sequence_item derivative type Trans2. Thus the incoming transaction Trans1 need to be converted into Trans2. Once again, Sequencer2s internal arbitration logic (provided by OVM) is used to arbitrate between Sequences 4,5 & Translation Sequence The point to be noted here is that, we need a path to send the Trans 1 out of Sequencer1 and be received by Translation Sequence. The problem is, Sequences being derived from ovm_sequence and ultimately ovm_object, does not support TLM channel declarations. One way to achieve this would be to define the required TLM channels (user_req_port & user_rsp_export) in Sequencer2 with which Translation Sequence is associated already. As the Translation Sequence has a readymade m_sequencer handle from OVM to access the associated Sequencer2, Translation Sequence simply has to say m_sequencer.user_req_port.get() to get the transactions from Sequencer1. One care that needs to be taken for the response path to work in the above scenario is that the respective seq_id, transaction_id and m_sequencer/p_sequencer fields of Trans1 & Trans2 need to be separately maintained without intermixing them, so that during the translation, only user fields get translated. For this, one way is to maintain extra set of seq_id, transaction_id and

    Driver

    Seq1

    Seq2

    Seq3

    Seq6

    Translation Sequence

    Seq4

    Indicates a conversion sequence to convert the Trans1 from Sequencer1 to Trans2 as required by Sequencer2. Uses m_sequencer.user_req_port.get() to get the transaction from the Sequencer1

    Transaction (Trans1)

    Transaction (Trans2)

    Sequencer2

    arbitration

    Sequencer2

    arbitration

    Sequencer2 user_req_port user_rsp_export

    Sequencer1 seq_item_port

    rsp_port

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    15

    m_sequencer/p_sequencer fields in Trans2 for Trans1 so that the response received can be properly co-related to the correct sequence and transaction numbers. Another way would be to maintain a req queue in the Trans2 so that when the response is received, it can be matched wih the reqs in the local queue and then co-related to the correct sequence and transaction numbers.

    6 Single Class / Multiple Analysis ports

    In a typical Scoreboard, we are required to connect two or more monitors. In OVM, this is done using analysis imports. Now, the Scoreboard will require to provide the write() function implementation for every analysis import instantiated. But a class cannot have two or more functions with same signature. This can be resolved by using an analysis FIFO after the analysis import so that the write() function implementation is provided by the analysis FIFO instance as shown below. (Refer to Figure 10) (Code 10, 11, 12)

    Figure 10 Analysis FIFO connection model monitor & score-board

    But, at times there is a requirement to provide a write() function implementation by the user, customized to take care of some project requirements. Thus we need a solution to have multiple write() functions defined in the same Scoreboard class. OVM provides a macro to do this, known as `ovm_analysis_imp_decl(). User passes a string name to the macro that he/she wishes to have appended. This basically provides:

    1. An import class with a ovm_analysis_imp as its signature 2. It also provides a signature to a write function with write () as its name.

    User simply instantiates above import and connects to the respective monitor. Also, user codes the above function that gets called whenever the connected monitor writes to its analysis port. This function is coded by user as per his/her project requirements. Note that though monitor simply calls its port.write() function, in turn the connected subscribers import.write() function gets called automatically.

    SCOREBOARD

    Write Monitor

    Read Monitor

    Score-boarding

    Logic

    write()

    write()

    fifo.get()

    fifo.get()

    tlm_analysis_fifo

    ovm_analysis_port

    ovm_analysis_export

    fifo.analysis_export

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    16

    Code 10 Monitors to be connected to score-board

    Code 11 Agent code showing monitor & scoreboard connection

    class MyReadMonitor extends

    ovm_monitor;

    ovm_analysis_port #(MyTrans1) ap;

    task run();

    MyTrans1 Tr;

    //Monitor logic

    ----

    ----

    ap.write(Tr);

    endtask

    endclass: MyReadMonitor

    class MyWriteMonitor extends

    ovm_monitor;

    ovm_analysis_port #(MyTrans1) ap;

    task run();

    MyTrans1 Tr;

    //Monitor logic

    ----

    ----

    ap.write(Tr);

    endtask

    endclass: MyWriteMonitor

    class MyAgent extends ovm_agent;

    MyWriteMonitor wrMon;

    MyReadMonitor rdMon;

    MyScoreboard scbd;

    function void connect();

    wrMon.ap.connect(scbd.userWrData_imp);

    rdMon.ap.connect(scbd.userRdData_imp);

    endfunction

    endclass: MyAgent

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    17

    Code 12 Score-board showing implementation

    `ovm_analysis_imp_decl(_UserWrData)

    `ovm_analysis_imp_decl(_UserRdData)

    class MyScoreboard extends ovm_scoreboard;

    ovm_analysis_imp_UserWrData #(MyTrans1, MyScoreboard) userWrData_imp;

    ovm_analysis_imp_UserRdData #(MyTrans1, MyScoreboard) userRdData_imp;

    MyTrans2 WrTransQue[$];

    MyTrans2 RdTransQue[$];

    function void write_UserWrData (MyTrans1 uWrTrans);

    MyTrans2 WrTrans2;

    //Convert uWrTrans to WrTrans2

    ------

    ------

    WrTransQue.push_back(WrTrans2);

    endfunction : write_UserWrData

    function void write_UserRdData (MyTrans1 uRdTrans);

    MyTrans2 RdTrans2;

    //Convert uRdTrans to RdTrans2

    ------

    ------

    RdTransQue.push_back(RdTrans2);

    endfunction : write_UserRdData

    task void run ();

    MyTrans2 WrTrans2;

    MyTrans2 RdTrans2;

    fork

    begin

    forever begin

    if(WrTransQue.size() > 0) begin

    WrTrans2 = WrTransQue.pop_front();

    //Process Write Trans

    ------

    ------

    end

    end

    end

    begin

    forever begin

    if(RdTransQue.size() > 0) begin

    RdTrans2 = RdTransQue.pop_front();

    //Process Read Trans

    ------

    ------

    end

    end

    end

    endtask : run

    endclass: MyScoreboard

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    18

    7 SV world to C world - Host Communication

    In case of SOC projects, often there is a need to communicate across from SV World to C World and back, to accomplish a particular test scenario. Now, in case of Module Level Verification Environments, where embedded host processor is typically absent, SV to C communication and back can simply be SV DPI Calls. But when embedded host processor is in place at Chip Level Verification Environment, shared memory is one way to achieve the communication between the SV and C Worlds. Typically, we randomize the control parameters in the SV World as per the constraints specified in the test-case/sequence/transfer class, but the programming of DUT registers for DUT initialization has to be performed by the embedded processor only, as per the real world SOC requirement. The idea here is to reuse the C code written at Module Level Verification into the Chip Level Verification. Thus there is a need to send across the randomized set of data from SV World to the C World. Once the C program executes on the embedded processor (or through DPI call at Module Level) and utilizes the data that came from SV World, it now has some programming sequence data ready to program the DUT registers. But to actually perform this programming, this data has to be brought back from the C World to the SV World where some SV module can drive the DUT Register Programming interface using the data received from the C World. To accomplish the above communication, reusable verification blocks can be defined to be used across various project modules. One of the proposed definitions of these blocks is that we define a Host Adapter block and a Host Requester block. [Refer to figure 11] There will be a Singleton instance of Host Adapter in a project at any given time. Every SV Module that wishes to send data to the C World first extends the host requester block for customizing the data to be sent across as per that modules requirement and then connects to the singleton Host Adapter instance using a host requester channel (TLM Channel). A generic data structure can be defined that is interpreted by any Host Requester and Host Adapter. This data structure can contain following fields: block_id, task_id, data[], control[]. The contents of data [] and control[] can be customized by the individual modules as per their requirement. Every Module Level Verification Environment provides a C file containing the tasks required to execute to achieve that Modules DUT Register Programming. Also, in that file, it provides a host task table consisting of entries of task string name and corresponding function pointer. When a Host Requester sends a request in the form of a structure defined above, to the Host Adapter, it gets stored in the Adapters in-built Queue (FIFO). The various barriers defined in Adapter like the init_barrier, run_barrier, check_barrier etc pops out the request from Queue one-by-one at the appropriate barrier timing and calls the Host Adapter Generic C function process requests() for handling the requests. In case of Module Level Verification Environment, as discussed before, this will be purely a DPI-C call. In case of Chip Level Verification Environment, this will be through a shared memory so that the Adapter Generic C function(s) running on embedded host processor can pick up the request through shared memory and execute it.[ Refer to figure 12] This Generic C function looks at the block_id from the request and figures out which host task table to look into. Then it uses the task_id in the form of a string from the request to lookup for this function in this table. Once it finds it, it simply calls the mapping function pointer in the found entry

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    19

    with the data [] and control[] as arguments else flags a fatal error. This User C function called by the Generic C function may result in a call, back to SV World. Again in case of Module Level Verification Environment, this will simply be a DPI SV call to the SV Adapter exported function(s). In case of Chip Level Verification Environment, this will be through a shared memory so that some Adapter SV process waiting for the C side to setup data in shared memory gets kicked off seeing the data there and then executes the associated tasks in the DUT Register Programming module in the SV domain to get the appropriate DUT Registers programmed. In a similar fashion, interrupts handling can be taken care of in the Module Level Verification Environments where actual host processor is missing, so the ISR routine gets called through the DPI C calls. At Chip Level, there will be actual processor to handle the interrupts anyways.

    Figure 11 Host Communication module-level setup

    Host Requester

    Host Adaptor

    Host Master Agent

    Host Sequence

    Block C Routines

    Block Test bench

    Block Environment

    Host Requestor Channel

    Host Environment

    DPI

  • System Verilog + OVM: Mitigating Verification Challenges & Maximizing Reusability

    20

    Figure 12 Host communication module/SoC setup

    To be continued..........

    PCIe

    SATA

    USB

    PCIe Host Requestor

    SATA Host Requestor

    USB Host Requestor

    PCIe user C functions & func table

    SATA user C functions & func table

    USB user C functions & func table

    Host Adaptor Generic C code

    Singleton Host Adaptor

    DUT Programming

    Interface/Module

    DUT

    Host Requestor

    Channel

    DPI/Shared Memory

    communication

    IntroductionOOPs Design Patterns (Singleton Instantiating One Object)Use of Parameterized Interface(s) in a PackageHarness- a Complete Sub-system definitionSequencer LayeringSingle Class / Multiple Analysis portsSV world to C world - Host Communication