efabless / EF_UVM

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Overview

EF_UVM is a resuable UVM testbench environment based on uvm-python library. The environment could be used for any IP/design after wrapping the design with this AMBA wrappers generator.

Before usage, it is recommended to get familiar with cocotb which is a framework which enables verifying Verilog RTL using Python. Also, if you are new to UVM (Universal Verification Methodolgy), it is recommended to check this. Finally, you should check uvm-python which is a Python and cocotb-based port of the SystemVerilog Universal Verification Methodology (UVM)


Quick Links


Architecture

As shown in Figure 1 below, The environment consisted of two sub environmnet one for the bus wrapper and the other is for the IP. Most of the testbench components can be used without modification and some should be updated for each IP.

alt text Figure 1: Environment diagram.

Testbench overview

The testbench is written in Python using the UVM-Python library. Since the testbench is based on UVM, it adheres to the UVM standard. It also inherits the powerful features of UVM, such as reusability, scalability, and automation. As the design should consist of two parts, the bus wrapper (APB, AHB, etc.) and the IP, the testbench is also divided into two main environments: the Bus Environment and the IP Environment. Each environment is responsible for monitoring, driving, and collecting coverage for one part of the design. The two environments should then communicate with the reference model and the scoreboard. Each environment should have its separate sequence/sequences connected to its sequencer. If any dependency between the parts' sequences exists, it should be handled by the test.

Environment

The enviroment component is used to encapsulates verification components. In this architecture, there are two enviroment classes; one for the bus wrapper; bus_env and the other for the ip itself; ip_env. Both of them inheret from UVMEnv class.

Components:
  • Agent
  • Coverage collector
  • Logger.
Connection between components
  • The agent send data to the coverage collector and logger.
Connection with other components
  • The environment should be able to send data to the scoreboard and reference model.
  • The environment should be able to send and receive data from the sequence.
  • The environment should be be connected with one of the design interfaces.

Agent

The agent component is used to encapsulates a sequencer, driver, and monitor. In this architecture, there are two enviroment classes; one for the bus wrapper; bus_agent and the other for the ip itself; ip_agent. Both of them inheret from UVMAgent class.

Components
  • Sequencer
  • Driver
  • Monitor.
Connection between components
  • Driver and sequencer should have bidirectional connection.
Connection with other components
  • Monitor should be able to send data outside of the agent.
  • Sequencer should be connected with sequence/sequences by the test.
  • Monitor and driver should be connected to the design interface.

Monitor

The monitor component is used to capture transactions and pass them to other components for further analysis or processing. It acts as a data capture mechanism within the testbench environment. There are three monitor classes in the bus enviromnt; one for AHBL bus wrapper bus_ahb_monitor, one for APB bus wrapper bus_apb_monitor, and one for interrupts bus_irq_monitor. There is another monitor to capture transactions related to ip external interface; ip_monitor. All monitors inheret from UVMMonitor class.

NOTE: only one of the bus monitors (bus_ahb_monitor or bus_apb_monitor) is used in the test according to which wrapper is being verified

Connection with other components
  • Monitor should be able to send data outside of the agent.
  • Monitor should be connected to an hdl interface.

Driver

The driver component is used to drive transactions to the design under test (DUT). It interacts with the sequencer to fetch and execute the transactions. There are three drivers in the architecture; one to drive the AHBL bus ports bus_ahb_driver, one to drive APB bus ports bus_apb_driver, the last one is to drive ports related to the ip ip_driver. All driver classes are inherited from UVMDriver class.

NOTE: only one of the bus drivers (bus_ahb_driver or bus_apb_driver) is used in the test according to which wrapper is being verified

Connection with other components
  • Driver should be able to send and receive data from the sequencer.
  • Driver should be connected to an hdl interface.

Sequencer

The sequencer component is used to control the flow of transactions between the driver and the DUT, as well as communicating with the sequence to coordinate the generation and execution of transactions. There are two sequencer one for the bus bus_sequencer and the other for the ip ip_sequencer. Both of the sequencer inheret from UVMSequencer class.

Connection with other components
  • Sequencer should be able to send and receive data from the driver.
  • Sequencer should be able to send and receive data from the sequence.

Coverage

The coverage component is used to observe the transactions captured by the agent and extracting coverage information from them. There are two coverage classes; one for the bus bus_coverage and the other for the ip ip_coverage. Both of the sequencer inheret from UVMComponent class.

Connection with other components
  • Coverage should be able to receive data from the agent/monitor.

Logger

The logger component is used to capture transactions and store them in a log file. There are two logger classes; one for the bus bus_logger and the other for the ip ip_logger. Both of the sequencer inheret from UVMComponent class.

Connection with other components
  • Logger should be able to send and receive data from the agent/monitor.

Reference model

The ref_model is a golden model or a trusted source of expected behavior, against which the actual behavior of the DUT is compared. It provides a basis for verifying the correctness of the DUT's functionality.

Connection with other components
  • Reference model should be able to be able to receive data from the two environments.
  • Reference model should be able to send expected data to the scoreboard.

Scoreboard

The scoreboard is used to compare the actual results produced by the DUT with the expected results from the reference model. It helps in determining the correctness of the DUT's behavior by monitoring and analyzing the transactions and their outcomes.

Connection with other components
  • Scoreboard should be able to receive data from the reference model.
  • Scoreboard should be able to send data from the 2 environments.

Test

The test manages the overall verification process. It coordinates the creation and execution of sequences, manages the test environment, and handles any dependencies between different parts of the testbench. Details of how to write a test is provided here.

Sequence Item

UVM sequence itme is the representation of transaction-level data for verification in a Universal Verification Methodology (UVM) environment. It represents a single transaction or data item that is passed between all the relevant components, including the monitor, sequence, sequencer, driver, etc. It encapsulates the information and behavior related to a specific transaction within the testbench environment. In the architecture, there are two item classes, one for the bus bus_item and the other for the ip ip_item. both of them inherets from UVMSequenceItem class.


IPs verified using EF_UVM

  • EF_UART : A Universal Asynchronous Receiver Transmitter
  • EF_GPIO : A generic 8-bit General Purpose I/O (GPIO)
  • EF_TMR32 : A 32-bit timer and PWM generator

Running tests

This section will discuss how to run tests for IPs which have an existing EF_UVM enviroment and what is the expected output. You can find a list for those IPs here. If you want to create UVM enviroment for a new IP, please refer to this section.

Prerequisites

TODO: update this section after creating the new flow

Verify APB wrapper

make run_all_tests
make run_<test_name>
make run_all_tests TAG=<new_tag> BUS_TYPE=APB

Verify AHBL wrapper

make run_all_tests BUS_TYPE=AHB
make run_<test_name> BUS_TYPE=APB
make run_all_tests TAG=<new_tag> BUS_TYPE=APB

Results obtained

After running the test, a directory called sim will be created with the following structure.

└── <tag_name>
    ├── compilation
    │   └── sim.vvp
    ├── <Test1_name>
    │   ├── coverage.yalm
    │   ├── loggers
    │   │   ├── logger_bus.log
    │   │   ├── logger_ip.log
    │   │   ├── logger_irq.log
    │   │   └── regs_write.log
    │   ├── passed
    │   ├── results.xml
    │   ├── test.log
    │   ├── top_module.py
    │   ├── tr_db.log
    │   └── waves.vcd
    └── <Test2_name>
        ├── coverage.yalm
        ├── loggers
        │   ├── logger_bus.log
        │   ├── logger_ip.log
        │   ├── logger_irq.log
        │   └── regs_write.log
        ├── passed
        ├── results.xml
        ├── test.log
        ├── top_module.py
        ├── tr_db.log
        └── waves.vcd
    

TODO: explain the improtant output files


Steps to verify new IP

To verify an IP using EF_UVM enviroment, all the components highlighted with red in the architectutre should be updated. New classes specific to the IP will be created and they will inheret from the corressponding class. Then, the object type should be ovverridden in the test. Here are the steps to follow to create a test.

1. Create verilog top level

A verilog file that instantiate the wrapper and contains all the top level signal and information about how to dump the waves and time step should be added. An example of the top level module is provided here.

2. Create interface

Interface mapping of the verilog signals to testbench is needed. This is done using by inherite from class sv_if and mapping the signals to the testbench. You can check uart_if for refrence.

3. Create the item class

An item class for the ip should be created and should inherit from the ip_item class. Three functions in the class should be overridden:

  • __init__ function should have variables representing the item
  • convert2string return the string representation of the item
  • do_compare has condition to compare the item with the another item.

You can check uart_item for refrence.

4. Create monitor class

A customized monitor class should be created and should inherit from ip_monitor class. Mostly, only the run_phase function should be overridden. The monitor run phase should continuously observe the the design under test (DUT) interface and convert it to transaction level item (UVMSequenceItem). You can check uart_monitor for refrence.

5. Create driver class

A customized driver class should be created and should inheret from ip_driver class. Like the monitor, only the run_phase function should be overridden. In the run phase, the driver should recieve the UVMSequenceItem and convert it to pin-level signals to interact with the design under test (DUT). You can check uart_driver for refrence.

6. Create reference model

A refrence model should be created which inherits from the ref_model class. The model primary role is to act as a representative or mimic of the actual hardware components, including the IP and the bus. You can check ref_model for refrence.

7. Create Sequences

A sequence is a collection of UVM sequence items that will be used to drive the testbench. The sequence should be updated after each test. sequences should be connected to the sequencers as the testbench has 2 sequencers, usually 2 more sequences are needed.

  • [] TODO: Add example from uart or any ip

8. Add functional Coverage

A coverage class should be created and should inherit from ip_coverage class. The coverage component recieves transactions from the agent and should utilize cocotb_coverage to create Cover Points relative to the IP to ensure that all cases are covered. You can check uart_coverage and uart_cov_groups for refrence.

9. Create Logger

A customized logger class should be created and should inheret from ip_logger class. Two functions in the class should be overridden:

  • __init__ function should update self.header according to the ip sequence item
  • logger_formatter should return the relative components from the sequence item

You can check uart_logger for refrence.

10. Create Test

The test should have the following:

  1. asynchronus function with @cocotb.test() decorator.
TODO [more explaination needed]
  1. Base test class which inherets from UVMTest class.
TODO [more explaination needed]
  1. Test classes which inherets from the base test class and ovveride the run_phase function. In the run phase, sequence objects should be created and .start(<sequencer>) function should be used and the relative sequencer should be passed (either bus or ip sequencer).

11. Create Makefile

You can copy this Makefile as a refrence and Update the following:

  • verilog files paths
  • yaml/json file path
  • tests names.

Contributing

TODO

Contributing Guidelines
  1. TODO

License

TODO


About


Languages

Language:Python 96.4%Language:Verilog 1.5%Language:Tcl 1.2%Language:Makefile 1.0%