SV Ovm Paper Part1
SV Ovm Paper Part1
SV Ovm Paper Part1
Authors
Parag Goel [pgoel@amcc.com]
Pushkar Naik [pnaik@amcc.com]
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.
Table of Contents
Contents
1
Introduction -------------------------------------------------------------------------------------------------------------------------------- 4
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
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
Statistics Collector
Driver
Scoreboard
Bus Monitor
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
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
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]
Backdoor Path
Memory
model
Protocol
BFM
Test sequence
includes
initialization +
traffic
DUT
Now, lets see what goes into the user side. The steps are as follows:
Code 3 Example for Singleton memory usage
//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);
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.
DUT
TESTBENCH
Connection
package (pkg)
Virtual
Interface (vif)
Global defines
package
`defines
enums
parameters
Driver
Connection Module
vif
vif
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.
AXI TB
Subsystem
AXI
DUT
TEST
BENCH
USB
USB TB
Subsystem
DUT PORTS
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.
TESTBENCH
USB
Agent
module top();
USB
Sequenc
er
USB
Driver
USB
Monitor
AXI
Agent
AXI
Sequenc
er
AXI
Driver
endmodule
S
V
I
N
T
E
R
F
A
C
E
S
A
X
I
DUT
U
S
B
B
AXI
Monitor
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].
USB Harness
USB
Connection
Module
USB
Agent
USB
Sequencer
USB
Driver
USB
Monitor
AXI Harness
AXI
Connection
Module
AXI
Agent
AXI
Sequencer
AXI
Driver
AXI
Monitor
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]
reset,
//USB Intf
txready,
datain,
. . . .
dataout,
txvalid,
input
input
//AXI Intf
Reset,
wrAddr,
. . . .
rdData);
clk;
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
Top
Module
Test
cases
Test
Environment
AXI
Connection
Module
USB
Connection
Module
USB
Agent
USB
Sequencer
USB
Driver
USB
Monitor
AXI
Agent
AXI
Sequencer
AXI
Driver
AXI
Monitor
12
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.
Transaction
(Trans2)
Transaction
(Trans1)
Seq4
Driver
Translation Sequence
Sequencer
Seq1
Seq2
Seq3
Seq6
Sequencer
arbitration
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
Here we suggest an OVM reusable approach, where Sequencers Arbitration Logic can be reused in
achieving the above objective [Refer to Figure 9].
13
Transaction
(Trans2)
Transaction
(Trans1)
Seq4
Seq1
Translation
Sequence
Sequencer2
Seq2
Sequencer1
Driver
Seq3
Seq6
user_req_port
seq_item_port
user_rsp_export
rsp_port
Sequencer2
arbitration
Sequencer2
arbitration
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.
SCOREBOARD
Write
Monitor
write()
tlm_analysis_fifo
Read
Monitor
write()
fifo.get()
Scoreboarding
Logic
fifo.get()
ovm_analysis_port
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(<_userString>). 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<_userString> as its signature
2. It also provides a signature to a write function with write<_userString> () 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<_userString>()
function gets called automatically.
15
16
`ovm_analysis_imp_decl(_UserWrData)
`ovm_analysis_imp_decl(_UserRdData)
class MyScoreboard extends ovm_scoreboard;
ovm_analysis_imp_UserWrData
ovm_analysis_imp_UserRdData
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
17
18
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.
Block Test bench
Host Environment
Block Environment
Host Master
Agent
Host Sequence
Block C
Routines
DPI
Host
Requestor
Channel
Host Adaptor
Host Requester
19
PCIe
SATA
USB
PCIe Host
Requestor
SATA
Host
Requestor
USB Host
Requestor
Host
Requestor
Channel
Singleton
Host Adaptor
DUT
Programming
Interface/Module
DPI/Shared
Memory
communication
PCIe user C
functions &
func table
Host
Adaptor
Generic
C code
SATA user C
functions &
func table
USB user C
functions &
func table
DUT
To be continued..........
20