Giter VIP home page Giter VIP logo

uvm-python's Introduction

Build Coverage Status PyPI version

UVM library for Python

uvm-python is a Python and cocotb-based port of the SystemVerilog Universal Verification Methodology (UVM) 1.2. The code has been extensively tested using Icarus Verilog (iverilog) and Verilator.

Currently, there are no open source/free tools available for working with SystemVerilog UVM. However, with the use of cocotb, testbenches can be written in Python, making it possible to work with both free and proprietary simulators. The uvm-python package offers an API that is similar to the original SV-UVM version, making it easy for users to transfer their UVM verification skills and API knowledge from SV to Python.

For those looking to port a larger amount of SystemVerilog code to use uvm-python, the package includes a regex-based script, bin/sv2py.pl, that can be used as a starting point. However, note that significant manual edits may still be required to ensure the code works correctly.

For more information, please refer to the uvm-python documentation and user's guide.

Documentation:

Documentation

The documentation is available on readthedocs.io in uvm-python HTML documentation.

Installation

You can install uvm-python as a normal Python package. It is recommended to use venv to create a virtual environment for Python prior to installation.

Install from PyPi using pip:

python -m pip install uvm-python

or directly from source files (for the latest development version):

git clone https://github.com/tpoikela/uvm-python.git
cd uvm-python
python -m pip install . # If venv is used
# Or without venv, and no sudo:
python -m pip install --user .  # Omit --user for global installation

See Makefile for working examples. You can also use Makefiles in test/examples/simple as a template for your project.

Running the examples and development

See test/examples/simple/Makefile for working examples. More features/examples will be added incrementally.

To run all tests:

    SIM=icarus make test  # Use iverilog as a simulator

To run unit tests only:

    make test-unit  # Does not require simulator

Minimal working example

uvm-python must be installed prior to running the example. Alternatively, you can create a symlink to the uvm source folder:

cd test/examples/minimal
ln -s ../../../src/uvm uvm
SIM=icarus make

You can find the source code for this example here. This example creates a test component, registers it with the UVM factory, and starts the test.

You can execute the example by running SIM=icarus make. Alternatively, you can run it with SIM=verilator make.

# File: Makefile
TOPLEVEL_LANG ?= verilog
VERILOG_SOURCES ?= new_dut.sv
TOPLEVEL := new_dut
MODULE   ?= new_test
include $(shell cocotb-config --makefiles)/Makefile.sim

The top-level module must match TOPLEVEL in Makefile:

// File: new_dut.sv
module new_dut(input clk, input rst, output[7:0] byte_out);
    assign byte_out = 8'hAB;
endmodule: new_dut

The Python test file name must match MODULE in Makefile:

# File: new_test.py
import cocotb
from cocotb.triggers import Timer
from uvm import *

@uvm_component_utils
class NewTest(UVMTest):

    async def run_phase(self, phase: UVMPhase):
        phase.raise_objection(self)
        await Timer(100, "NS")
        uvm_info("NEW_TEST", "Test passed, all OK", UVM_MEDIUM)
        phase.drop_objection(self)


@cocotb.test()
async def test_dut(dut):
    await run_test('NewTest')

Current status

Testbenches can already be written with all the typical UVM components. UVM Phasing is in place, and working. Stimulus can be generated using (even hierarchical) sequences. Register layer supports already read/write to registers (via frontdoor), and to memories (frontdoor and backdoor). TLM 1.0 is implemented, put/get/analysis interfaces are done, and master/slave interfaces work. Initial implementation of TLM2.0 has also been added. The table below summarizes the status:

Feature Status
TLM1.0 Done
TLM2.0 Done
Components Done
Phases Done
Objections Test and env-level objections work
Sequences Partially done, hier sequences work
Registers Reg/mem access working, built-in sequences partially done

Please try it out, and let me know if something you require should be added, or even better, add it yourself, test it and create a pull request!

HDL Simulators

Tested with Icarus Verilog (iverilog v13.0 (s20221226-498-g52d049b51)) and verilator (v5.020-176-g953249aa4).

Icarus Verilog and verilator are free simulators, which can be used with cocotb. uvm-python uses cocotb to interface with these simulators. Memory backdoor access has issues with packed multi-dimensional arrays in verilator. Also, some other examples are not working with verilator yet.

Proprietary simulators that work with cocotb should work with uvm-python as well, but haven't been tested.

Related projects

uvm-python's People

Contributors

cmarqu avatar mballance avatar mgielda avatar rodrigomelo9 avatar sikoverilog avatar sjalloq avatar tpoikela avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uvm-python's Issues

Typo in uvm_reg_field.py

I've been starting to use my register model and have been confused at why I can't trigger an error on reg.mirror(). It looks like there's another typo in uvm_reg_field.py where the initial value of m_check is set to UVM_NO_CHECK instead of UVM_CHECK.

In the SV version, the configure method checks if the field is volatile or not and sets the check field appropriately:

   function void uvm_reg_field::configure(uvm_reg        parent,
                                          int unsigned   size,
                                          int unsigned   lsb_pos,
                                          string         access,
                                          bit            volatile,
                                          uvm_reg_data_t reset,
                                          bit            has_reset,
                                          bit            is_rand,
                                          bit            individually_accessible); 
      m_parent = parent;
      if (size == 0) begin
         `uvm_error("RegModel",
            $sformatf("Field \"%s\" cannot have 0 bits", get_full_name()));
         size = 1;
      end
   
      m_size      = size;
      m_volatile  = volatile;
      m_access    = access.toupper();
      m_lsb       = lsb_pos;
      m_cover_on  = UVM_NO_COVERAGE;
      m_written   = 0;
      m_check     = volatile ? UVM_NO_CHECK : UVM_CHECK;

In uvm_reg_field.py, the variable is set in the __init__() method to UVM_NO_CHECK and then in configure() method, if it's volatile, the same value is written. I think the initial value should be changed to:

   def __init__(self, name='uvm_reg_field'):
        """
        This method should not be used directly.
        The `UVMRegField.type_id.create()` factory method
        should be used instead.

        Args:
            name: (str): Name of the register field
        """
        UVMObject.__init__(self, name)
        self.value = 0  # Mirrored after randomize()
        self.m_mirrored = 0  # What we think is in the HW
        self.m_desired = 0  # Mirrored after set()
        self.m_access = ""
        self.m_parent = None  # uvm_reg
        self.m_lsb = 0
        self.m_size = 0
        self.m_volatile = False
        self.m_reset = {}  # string -> uvm_reg_data_t
        self.m_written = False
        self.m_read_in_progress = False
        self.m_write_in_progress = False
        self.m_fname = ""
        self.m_lineno = 0
        self.m_cover_on = 0
        self.m_individually_accessible = False
        self.m_check = UVM_CHECK  # uvm_check_e

and then the configure() method doesn't need to change (although removing the else case would be a positive):

   def configure(self, parent, size, lsb_pos, access, volatile, reset, has_reset, is_rand,
            individually_accessible):
 # ...snip...
        if volatile:
            self.m_check = UVM_NO_CHECK
        else:
            self.m_check = self.m_check

test uvm-python/test/examples/integrated/ubus/examples for "read modify write" can not be randomized with the uvm_do_with

Hi, I ve just installed UVM-python and I was trying the example in

uvm-python/test/examples/integrated/ubus/examples

with

make

it reaches the end and passes and says "UVM_ERROR: 0" and also "UVM_FATAL: 0"

but trying to add constraints in the uvm_do_with sequences in

uvm-python/test/examples/integrated/ubus/examples/ubus_example_master_seq_lib.py

does not lead to them being taken into account..

I have made some (not impressive) progresses if I do what I show in the attached .py python files but nevertheless I get the results also attached here as .vcd file, i.e. I obtain to write at the same address that I read in the 1st step and really to write the "read data plus 1" but then on the 2nd read (which is the 3rd operation, after the "WRITE" of "read modify write".... I get from this address completely unrelated [data...](url
ubus_master_seq_lib.py.txt
ubus_transfer.py.txt
ubus_example_master_seq_lib.py.txt
Snapshot_2021-03-24 17-24-18

)

may be I am doing something stupid or is this not yet supported completely ?
thx a lot!

Using uvm-python for with custom build infrastructure

I am trying to integrate cocotb inside larger build infrastructure. What is the best way to do this? I thought venv might work. Any suggestions? Thanks.

Creating a venv and install UVM-Python package:

python3.10 -m venv …/uvmpy/venv
cd …/uvmpy
git clone https://github.com/tpoikela/uvm-python.git
cd uvm-python
python -m pip install .

I see cocotb-config under ../venv/bin

I run this command in a new terminal and different directory:

source .../uvmpy/venv/bin/activate.csh

which cocotb-config
…/uvmpy/venv/bin/cocotb-config

Then run an example and I get this error:

cp -rf …/uvmpy/uvm-python/test/examples .
cd examples/minimal

(Update Makefile: ../../.. in PYTHONPATH changed to the location of …/uvmpy/uvm-python)

make sim
Traceback (most recent call last):
  File “…/uvmpy/venv/bin/cocotb-config", line 5, in <module>
    from cocotb.config import main
  File "…/uvmpy/venv/lib/python3.10/site-packages/cocotb/__init__.py", line 43, in <module>
    import cocotb.handle
  File "…/uvmpy/venv/lib/python3.10/site-packages/cocotb/handle.py", line 39, in <module>
    from cocotb import simulator
ImportError: cannot import name 'simulator' from partially initialized module 'cocotb' (most likely due to a circular import) (…/uvmpy/venv/lib/python3.10/site-packages/cocotb/__init__.py)

I also sometimes see cocotb-config not found. Is there a way to use cocotb Makefiles without coco-tb-config?

uvm hw reset sequence bug

Hello,

I found a bug on uvm_hw_reset_sequence enum is not getting name rightly which is fixed now let me know how can i commit these changes

thanks
SanaUllah

Test failing

Using this package all my tests are executing and giving correct result.
But at the end report is failing. There is no log error found

Below is log
1000000.00ns ERROR cocotb.scheduler Failing test at simulator request before test run completion: Simulator shutdown prematurely
1000000.00ns ERROR cocotb.regression Test error has lead to simulator shutting us down

Correct way to clean up UVM objects

I've been using the register model I created and having now added more tests to a single file, I noticed I'm getting warnings that more than one uvm_reg_block have been instanced with the same name.

Am I supposed to be cleaning up each test somehow? Is there a particular helper method I should call?

Cheers.

uvm_info

How to save uvm_info into a log file,not only into terminal?

Cross TLM communication

@tpoikela
Can we use this python uvm package to create monitor and from analysis port receive transactions from sv uvm(cross packet transaction between two languages with tlm)?

What is the correct way to update the mirrored state of a register?

@tpoikela, here's an example I've been playing with tonight. I'm just trying to work out how I go about updating the mirrored value with that in the RTL. I've got a simple dut.sv that has an incrementing counter called count_q[31:0] inside a module called regfile. So the hierarchical path is dut.u_reg.count_q.

I hit a few snags along the way getting here, one of which needs a pull request which I'll sort out shortly. But my outstanding question is how am I supposed to get the register model to update the mirrored value of a UVMRegField?

I've not used UVM before so this is perhaps just a methodology question but perhaps I'm just supposed to manually update the value any time the TB logic wants to read the data?

#!/usr/bin/env python3

import sys
import cocotb
from cocotb.triggers import Timer, RisingEdge
from cocotb.clock import Clock
from uvm import UVMRegBlock, UVMReg, UVMRegField, UVMRegItem, uvm_hdl
from uvm.macros import uvm_object_utils
from uvm.reg.uvm_reg_model import *

class Register(UVMReg):
    def __init__(self, name):
        super().__init__(name, 32)

    def build(self):
        self.count = UVMRegField.type_id.create("count")
        self.count.configure(self, 32, 0, "RO", True, 0, True, False, False)
    
uvm_object_utils(Register)

class Regfile(UVMRegBlock):
    def __init__(self, name='regfile'):
        super().__init__(name, UVM_NO_COVERAGE)

    def build(self):
        self.count = Register.type_id.create("count_qs")
        self.count.configure(self, None, "count_q")
        self.count.build()

uvm_object_utils(Regfile)


@cocotb.test()
async def test(dut):
    regfile = Regfile("register_file")
    regfile.add_hdl_path("u_reg")
    regfile.build()

    uvm_hdl.set_dut(dut)

    cocotb.fork(Clock(dut.clk, 5, 'ns').start())
    dut.rst_n <= 1
    await RisingEdge(dut.clk)
    dut.rst_n <= 0
    await RisingEdge(dut.clk)
    dut.rst_n <= 1
    
    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)
    print(regfile.count.get_mirrored_value())
    
    await Timer(100,'ns')
    await RisingEdge(dut.clk)
    print(int(dut.u_reg.count_q.value))
    print("%s needs_update=%s"%(regfile.count.name, regfile.count.needs_update()))
    
    rw = UVMRegItem.type_id.create("pseudo-read_item", None, "")
    regfile.count.backdoor_read(rw)
    print("backdoor_value=%s"%rw.value[0])
    print("mirrored_value=%s"%regfile.count.get_mirrored_value()) 

prints

backdoor_value=21
mirrored_value=0

Bug in uvm_reg_map.py

There seems to be a SV-to-Python conversion typo in uvm_reg_map.py where Xget_bus_infoX() is called. The SV version of this method updates the 4 arguments passed in but the Python version returns a list. This list should override the parameters that are passed in. However, n_bits_init is not updated. I'll create a PR for this but I wanted you to look at how the byte_en is updated. It seems to be only set if the element_kind is UVM_FIELD. In the case of UVM_REG, the byte_en is left as -1. Is this intentional? Perhaps in the SV world this is treated as a twos complement number which sets all byte enables to 1?

In all methods that call Xget_bus_infoX, the following

    [map_info, size, lsb, addr_skip] = self.Xget_bus_infoX(rw, map_info, n_bits, lsb, skip)

should be modified to:

    [map_info, n_bits, lsb, skip] = self.Xget_bus_infoX(rw, map_info, n_bits, lsb, skip)

And looking at it, there is a difference between do_bus_write and do_bus_read where n_bits_init and n_bits are used respectively. I'm assuming these should be the same.

registers/vertical_reuse blk-level simulation fails with ghdl/VHDL DUT

When running the above-mentioned example, uvm_fatal is thrown. Looks like APB monitor does not register any items during simulation.

Commands to reproduce the issue:

cd test/examples/simple/registers/vertical_reuse
SIM=ghdl make TOPLEVEL_LANG=vhdl IMG=BLK SIMARGS="-- +UVM_TESTNAME=blk_R_test" SIM_BUILD=sim_build_blk

Expected result:
Test passes, and does not throw uvm_fatal.

type error

when I run minimal test I got type error
python 3.7.6
cocotb 1.3.1
info
Did you forget use @cocotb.coroutine decorator? uvm run_test() location.
Was there something I did wrong.

uvm_do doesn't work

I can use uvm_do_with but when I try uvm_do it fails with

File "uvm/base/sv.py", line 511, in randomize_with
            raise RandomizeError(
                       uvm.base.uvm_exceptions.RandomizeError: randomize_with() failed for kind=READ addr=C2 data=DEADBEEF [] is not a callable object

I guess the [] that is passed as constraint is the problem

await uvm_do_on_pri_with(seq_obj, SEQ_OR_ITEM, seq_obj.m_sequencer, -1, [])

when I try and replaced the [] with lambda: True it works.

UVM Python minimal test

I'm trying to run the minimal test which is the example test that comes with the uvm-python package. When I launch the test, it shows this error:

File "/prj/tbs/5g/sandiego/hw/main/users/hctseng/dev5g/prach4/uvm_python/uvm-python-master/test/examples/minimal/uvm/base/uvm_globals.py", line 441, in uvm_is_sim_active return simulator.is_running()
AttributeError: module 'simulator' has no attribute 'is_running'

Any ideas? I'm using QuestaSim version 2020.2.

Thanks,
Richard

examples/sv is failing ... any ideas?

Errors I see is with icarus, but vcs seems to be working fine. Any ideas?
...
-.--ns INFO gpi ..mbed/gpi_embed.cpp:105 in set_program_name_in_venv Using Python virtual environment interpreter at ./venv/bin/python
-.--ns INFO gpi ../gpi/GpiCommon.cpp:101 in gpi_print_registered_impl VPI registered
: Unable to open input file.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.