tree: c5254622bc494e2be05c5b5e4422a3a38625961d [path history] [tgz]
  1. __init__.py
  2. agent.core.tpl
  3. agent.sv.tpl
  4. agent_cfg.sv.tpl
  5. agent_cov.sv.tpl
  6. agent_pkg.sv.tpl
  7. base_seq.sv.tpl
  8. base_test.sv.tpl
  9. base_vseq.sv.tpl
  10. bind.sv.tpl
  11. csr_vseq.sv.tpl
  12. device_driver.sv.tpl
  13. driver.sv.tpl
  14. env.core.tpl
  15. env.sv.tpl
  16. env_cfg.sv.tpl
  17. env_cov.sv.tpl
  18. env_pkg.sv.tpl
  19. gen_agent.py
  20. gen_env.py
  21. host_driver.sv.tpl
  22. if.sv.tpl
  23. item.sv.tpl
  24. Makefile.tpl
  25. monitor.sv.tpl
  26. plan.md.tpl
  27. README.md
  28. README.md.tpl
  29. reg_block.sv.tpl
  30. sanity_vseq.sv.tpl
  31. scoreboard.sv.tpl
  32. seq_list.sv.tpl
  33. sim.core.tpl
  34. tb.sv.tpl
  35. test.core.tpl
  36. test_pkg.sv.tpl
  37. virtual_sequencer.sv.tpl
  38. vseq_list.sv.tpl
util/uvmdvgen/README.md

uvmdvgen: UVM agent & complete testbench boilerplate code auto-generation tool

uvmdvgen is a python3 based tool to generate the boilerplate code for a UVM agent as well as the complete UVM testbench for a given DUT. The tool generates all the relevant UVM-based classes including the package and the fusesoc core file to make it quickly plug-and-playable. The packages import the standard utility and library packages wherever applicable, to conform to our existing methodology and style.

When starting with a new DV effort, user goes through a copy-paste exercise to replicate an existing UVM testbench code to the current one and has to go though several debug cycles to get it working. This tool aims to eliminate that. Also, as a part of OpenTitan DV methodology, we have several utilities and base class structures (such as DV lib and CIP lib) that share all of the common code. By extending a new DV enviroment from the common code, the effort is drastically reducecd.

Setup

The tool uses the mako based templates, so the following tool is required as dependency:

$ pip3 install --user mako

Help switch (-h)

Running the tool with -h switch provides a brief description of all available switches.

$ util/uvmdvgen.py -h
usage: uvmdvgen.py [-h] [-a] [-s] [-e] [-c] [-ea [name] [[name] ...]]
                   [-ao [hw/dv/sv]] [-eo [hw/ip/<ip>/dv]]
                   [ip/block name]

Command-line tool to autogenerate boilerplate DV testbench code extended from dv_lib / cip_lib

positional arguments:
  [ip/block name]       Name of the ip/block for which the UVM TB is being
                        auto-generated

optional arguments:
  -h, --help            show this help message and exit
  -a, --gen_agent       Generate UVM agent code extended from DV library
  -s, --has_separate_host_device_driver
                        IP / block agent creates a separate driver for host
                        and device modes. (ignored if -a switch is not passed)
  -e, --gen_env         Generate testbench UVM environment code
  -c, --is_cip          Is comportable IP - this will result in code being
                        extended from CIP library. If switch is not passed,
                        then the code will be extended from DV library
                        instead. (ignored if -e switch is not passed)
  -ea agt1 agt2 [agt1 agt2 ...], --env_agents agt1 agt2 [agt1 agt2 ...]
                        Env creates an interface agent specified here. They are
                        assumed to already exist. Note that the list is space-
                        separated, and not comma-separated. (ignored if -e
                        switch is not passed)
  -ao [hw/dv/sv], --agent_outdir [hw/dv/sv]
                        Path to place the agent code. A directory called
                        <name>_agent is created at this location. (default set
                        to './<name>')
  -eo [hw/ip/<ip>/dv], --env_outdir [hw/ip/<ip>/dv]
                        Path to place the env code. 3 directories are created
                        - env, tb and tests. (default set to './<name>')

Generating UVM agent

The boilerplate code for a UVM agent for an interface can be generated using the -a switch. This results in the generation of complete agent with classes that extend from the dv library. Please see description for more details.

The tool generates an interface, item, cfg, cov, monitor, driver and sequence library classes. Let's take jtag as the argument passed for the name of the IP. The following describes their contents in each source generated:

  • jtag_if

    This is an empty shell of an interface. User is required to add content.

  • jtag_item

    This is an empty transaction packet extended from uvm_sequence_item.

  • jtag_agent_cfg

    This is the agent configuration object, it contains the virtual interface handle for jtag_if and is called vif.

  • jtag_agent_cov

    This is a coverage component extended from dv_base_agent_cov.

  • jtag_monitor

    This is the monitor component extended from dv_base_monitor. It provides the following items:

    • virtual protected task collect_trans(uvm_phase phase)

      This is a shell task within which user is required to add logic to detect an event, sample the interface and create a transaction object and write to the analysis port. This task is called in dv_base_monitor::run_phase.

  • jtag_driver

    This is the monitor component extended from jtag_driver which is typedef'ed in the pkg to dv_base_driver with the right parameter set. It provides the following items:

    • virtual task reset_signals()

      This task is for resetting the initial value of the vif signals.

    • virtual task get_and_drive()

      This task is used to get the next item from the sequencer, apply it to the interface and return the response back. This is again, an empty task at the moment.

    If the -s switch is passed, the tool creates jtag_host_driver and jtag_device_driver instead, and their contents are exactly the same.

  • seq_lib/jtag_base_seq

    This is extended from dv_base_seq.

  • seq_lib/jtag_seq_list

    This is a list of sequences included in one place.

  • jtag_agent_pkg

    This is the package file that includes all of the above sources and the imports the dependent packages.

  • jtag_agent.core

    This is the fusesoc core file that is used to generate the filelist for the build.

The tool does not create jtag_sequencer or jtag_agent classes separetely. Instead, it typedef's the dv_base_sequencer and dv_base_agent respectively with the right type-parameters in the pkg. The reason for this is having a dedicated sequencer and agent is not required since the dv_base_agent already has all the sub-component instantiations and connections; and dv_base_sequencer already has a handle to the agent cfg object and nothing more is typically needed.

Generating UVM environment & testbench

The boilerplate code for a UVM environment and the testbench for a DUT can be generated using the -e switch. This results in the generation of classes that extend from dv library. If the -c switch is passed, it extends from cip library. With -ea switch, user can provide a list of downstream agents to create within the environment. Please see description for more details.

The tool generates not only the UVM environment, but also the base test, testbench, top level fusesoc core file with sim target, Makefile that already includes the sanity and CSR test suite and more. With just a few tweaks, this enables the user to reach the V1 milestone much quicker. Let's take i2c_host as the argument passed for the name of the IP. The following is the list of files generated with a brief description of their contents:

  • env/i2c_host_env_cfg

    This is the env cfg object. It creates the downstream agent cfg objects that were passed using the -ea switch in the ``initialize()function which is called in thedv_base_test::build_phase()`. Since the cfg handle is passed to all env components, those downstream agent cfg objects can be hierarchically referenced.

  • env/i2c_host_env_cov

    This is the coverage component class. A handle of this class is passed to the scoreboard and the virtual sequencer so that covergroups can be sampled in the scoreboard as well as sequences.

  • env/i2c_host_reg_block

    This is the UVM reg based RAL model. This is created for completeness. The actual RAL model needs to be generated prior to running simulations using the regtool.

  • env/i2c_host_scoreboard

    This is the scoreboard component that already creates the analysis fifos and queues for the agents passed via -ea switch. It adds starter tasks for processing each fifo in a forever loop and invokes them in the run_phase using fork-join statement. If the -c switch is passed, it also adds a process_tl_access task that is extended from cip_base_scoreboard. This task provides a tilelink access packet for further processing.

  • env/i2c_host_virtual_sequencer

    This is the virtual sequencer used by all test sequences to run the traffic. It adds handles to downstream agent sequencers passed via -ea switch. Sub-sequences can be started on them via the p_sequencer handle.

  • env/seq_lib/i2c_host_base_vseq

    This is the base virtual sequence that user can use to add common tasks, functions and variables that other extended test sequences can reuse. For starters, it provides the i2s_host_init() task and do_i2c_host_init knob for controllability.

  • env/seq_lib/i2c_host_sanity_vseq

    This is the basic sanity test sequence that user needs to develop as the first test sequence. It extends from i2s_host_base_vseq.

  • env/seq_lib/i2c_host_csr_vseq

    This is the test sequence for the entire CSR suite of tests. It calls dv_base_vseq::run_csr_vseq_wrapper() task which is a complete test sequence. All the user needs to do is run the CSR tests and add exclusions if needed using the add_csr_exclusions() function provided.

  • env/seq_lib/i2c_host_vseq_list

    This is a list of test sequences included in one place.

  • env/i2c_host_env

    This is the env class that creates the downstream agents passed via -ea switch. It sets their correspodnding cfg objects (which are members of env cfg object) into the uvm_config_db. It also makes the analysis port connections in the connect_phase and sets the sequencer handles in the virtual sequencer.

  • env/i2c_host_env_pkg

    This is the env pkg file which includes all env classes and imports the dependent packages.

  • env/i2c_host_env.core

    This is the fusesoc core file for the env pkg compile unit.

  • tests/i2c_host_base_test

    This is the base test class. The base test class it extends from already creates the env and cfg objects, which are available for manipulation in UVM phases. This class's name would be supplied to UVM_TESTNAME plusarg to run tests using the UVM methodology.

  • tests/i2c_host_test_pkg

    This is the test pkg file which includes all test classes and imports the dependent packages.

  • tests/i2c_host_test.core

    This is the fusesoc core file for the test pkg compile unit.

  • tb/i2c_host_bind

    This is the assertion bind file that is compiled along with the testbench in a multi-top architecture. If the -c switch is passed, it adds the tlul_assert module bind to the i2c_host DUT.

  • tb/tb

    This is the top level testbench module that instantiates the DUT along with some of the interfaces that are required to be instantiated and connected and passed on the the uvm_config_db since the base DV/CIP library classes retrieve them. The user needs to look through the RTL and make additional connections as needed.

  • i2c_host_sim.core

    This is the top level fusesoc core file with the sim target. It adds the rtl and dv dependencies to construct the complete filelist to pass to simulator's build step.

  • Makefile

    This is the simulation Makefile that is used as the starting point for building and running tests using the make flow. It already includes the sanity and CSR suite of tests to allow users to start running tests right away.

  • plan.md

    This is the empty DV plan document that will describe the entire testbench. A template for this is available here.

Examples

util/uvmdvgen.py i2c -a

This will create ./i2c/i2c_agent and place all sources there.

util/uvmdvgen.py jtag -a -ao hw/dv/sv

This will create hw/dv/sv/jtag_agent directory and place all the sources there.

util/uvmdvgen.py i2c -a -s -ao hw/dv/sv

This will create the I2C agent with separate ‘host’ mode and ‘device’ mode drivers.

util/uvmdvgen.py i2c_host -e -c -ea i2c -eo hw/ip/i2c_host/dv

This will create the complete i2c_host dv testbench extended from CIP lib and will instantiate i2c_agent.

util/uvmdvgen.py dma -e -eo hw/ip/dma/dv

This will create the complete dma dv testbench extended from DV lib. It does not instantiate any downstream agents due to absence of -ea switch.

util/uvmdvgen.py chip -e -ea uart i2c jtag -eo hw/top_earlgrey/dv

This will create the complete chip testbench DV lib and will instantiate uart_agent, i2c_agent and jtag_agent in the env.