UVM and Python
==============

The Universal Verification Methodology (UVM) grew out of the Open Verification
Methodology (OVM) which grew out of the Advanced Verification Methdology (AVM)
which leveraged the SystemVerilog programming language.

Though this long lineage suggests that the UVM must be implemented in
SystemVerilog, this is not the case. The UVM is a class library, and a class
library can be implemented in any object oriented programming language.

**pyuvm** implements the UVM using Python.  Creating testbenches using Python
has several advantages over SystemVerilog:

   * The Python ecosystem is larger than the SystemVerilog ecosystem.  More
     developers understand Python than SystemVerilog, and Python has a long tradition
     of being the language of choice for large-scale object oriented projects.
   * Python is object-oriented, even more so than SystemVerilog, and so it is
     easier to deliver functions such as overridable factories in Python than
     SystemVerilog.
   * Python runs without a simulator, and so is faster than SystemVerilog.
   * Python forces the testbench developer to separate simulated and timed
     RTL code from testbench code.  This means that testbenches written with
     Python support accelerated testbenches with little, if any, modification.


While Python is an excellent testbench development language, the UVM is an
excellent Verification Library. Implementing the UVM using Python gives us
the best of both worlds.

Pythonizing the UVM
-------------------

Much of the UVM specification in IEEE-1800.2-2017 is driven by elements of
the SystemVerilog programming language.  Blindly implementing all that is in
the UVM specification is not only impossible (there are no parameters in Class
declarations, for example), but also unwise.

Many elements of Python make it much easier to create testbench code using
Python than SystemVerilog.  For example, there are no arcane issues of typing, and
Python readily provides generic tools for logging and interprocess communication.

Rather than attempting to mimic the UVM completely, this implementation focuses on delivering the
functionality of the UVM, even if this changes the details of how functionality is
delivered.  This section examines some differences between
the implementations.

Static Typing vs. Duck Typing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

SystemVerilog is a statically typed language. You declare variables to be of
a certain type in the source code before using them.  It is a relatively
weakly typed languaged (relative to VHDL).  You can declare a variable to be
a ``short int`` and another to be an ``integer`` and still add them with no problem.

Python using Duck Typing, which is form of dynamic typing.  Duck typing says
that if something looks like a duck, and acts like a duck, then we'll consider it
a duck.  That means we don't declare a variable to be of type ``duck``, instead we
call ``duck.quack()`` and see if we get an exception.

The UVM can be difficult to write because of its static typing. A lot of energy
goes into parameterizing classes to get the behavior you want, that problem
goes away in Python.  Instead, you see runtime errors if you mess up the typing.


Exception Handling
^^^^^^^^^^^^^^^^^^

Unlike SystemVerilog, Python provides the ability to raise and catch exceptions.
While a SystemVerilog programmer needs to check to be sure that an action will
work before attempting it, a Python programmer is more likely to try the action
and catch an exception if it arises.

Uncaught exceptions rise through the call stack and eventually cause the Python
to dump out the stack trace information and exit. Catching exceptions keeps the
program from terminating.

**pyuvm** Exceptions
^^^^^^^^^^^^^^^^^^^^

Review the documentation for the ``error_classes`` module to see the Exceptions defined in **pyuvm**.


Coding differences between SystemVerilog UVM and **pyuvm**
----------------------------------------------------------

The topics outline above lead to differences between the way **pyuvm** implements
behaviors vs. how SystemVerilog does it.  This section highlights these differences.

Underscore Naming
^^^^^^^^^^^^^^^^^

Python programs use camel casing to define classes, but **pyuvm** uses underscore
naming to match the IEEE specification.  ``uvm_object`` is named ``uvm_object`` not ``UvmObject``.


Decorators and Accessor Functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

SystemVerilog UVM sets and gets variable values using accessor functions such
as ``set_name()`` and ``get_name``. Python implements similar functionality using
the ``@property`` decorator.

While **pyuvm** could have changed all the accessor functions to properties, it implements
the IEEE 1800.2 spec and keeps the accessor functions.

``uvm_object_wrapper`` and Factories
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

SystemVerilog has relatively poor class manipulation mechanisms.  Most of
the class information has already been determined at compile time and dynamically
creating objects of different classes, or overriding one class with another, requires
considerable gymnastics.

Python, on the other hand easily handles classes.  Classes are objects just like
everything else in the language.

As a result, **pyuvm** does not need the macros we use in SystemVerilog to
register classes with the factory.  It does not have `uvm_object_utils` or `uvm_component_utils`
macros.  It registers all classes that extend ``uvm_void`` with the factory.


Using Python functionality instead of UVM functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The UVM defines methods that make up for SystemVerilog's relative
immaturity relative to Python.  For example ``uvm_object`` defines
a `get_type()` method to get the type of an object.  Python has a ``type()``
function that does the same thing for all objects.

Therefore, **pyuvm** raises ``UsePythonMethod`` if you call ``get_type()``.

``uvm_policy`` Class
^^^^^^^^^^^^^^^^^^^^^^

The ``uvm_policy`` Classes provide functionality that is built into
Python with the ``setattr`` and ``getattr`` methods.

There are no field macros and thus no need to implement this class.

Reporting Classes
^^^^^^^^^^^^^^^^^

We use Python logging instead of the UVM reporting system.
