The basis of this article was derived from practical experience. The scenario was this:
“Here is a DUT specification, we have no UVM environment for you to start with as a template, so go and find out how to generate one with Mentor’s UVM Framework (UVMF) template generation methodology.”
The Mentor UVMF documentation and examples provided great direction on how to generate a UVMF framework from scratch via, in this case, Python scripting. And then, boom, in fairly short order and from an architectural standpoint, you are suddenly presented with a UVM framework that has hundreds of files and a large directory structure consisting of tests, sequences, transactions, drivers, monitors, predictors, scoreboards, configuration, and coverage. All connected, compile-able, and simulate-able… and a bit overwhelming.
So, what do you do next? The generated tests have no idea what is in your DUT or DVE (Design Verification Environment) functional specifications, nor does it know how to get stimulus all the way to the DUT from the top test. Also, your predictors do not know what to expect and are not ready to support score-boarding. Of course, there are other customization requirements such as synchronizing the drivers and monitors to the DUT and the framework itself which is quite well covered in the existing Mentor documentation AND all good subjects for white papers none-the-less. This article will concentrate on one of these areas: how to customize the front end Test Control structure. It will utilize, specifically, the primary Mentor UVMF tutorial called “Generator Tutorial” as the base example. This article is really a “how to” guide vs. a technical dissertation, and should be immediately useful to verification folks with limited UVM background engaged in something similar to the stated scenario at the beginning of this text. Additionally, these techniques should be directly applicable to any UVM template generated by Mentor’s UVMF template generator methodology.
Considering the UVMF automated scripting,
“The python scripts provided automates the creation of the files, infrastructure and interconnect for interface packages, environment packages and project benches. Once generated, developers can promptly focus on adding functionality specific to the design and interfaces used.”
The latter part of this quote becomes the central point of interest here: customizing the generated UVM Framework.
Once the generator tutorial guide is digested and the example is working, the substance of this article can be readily adapted thereon. In particular, the task becomes how to customize the front end of the environment in order to have manual control of the ALU inputs at the test level. In the published Generator Tutorial, all of the ALU inputs are randomized at the input sequence to the ALU in driver. This article will demonstrate how to extend that stimulus control out to top level tests, via adding/extending sequences/tests between the top test and the ALU in driver.
Therefore, this article will consist of a step-by-step process that will include the addition of new files to the tutorial UVMF file set, as well as modifications to existing UVMF files. All changes/additions were integrated and successfully simulated. Figure ALU DUT Block Diagram, on the opposite page, shows the simple ALU DUT with three inputs and one output. The modifications/additions to the DVE include manual control of the ALU “A” and “B” inputs only, while the “Operator” input was left randomized.
Section 8 features a list of affected files with their paths included, and can be obtained at TBD if desired. However, there is enough detail in this article to perform the edits manually.
Figure 1 - ALU DUT block diagram
The focus of this article starts where the Mentor document “ALU UVM Framework Step By Step Guide” ends. The guide does an excellent job of detailing the UVMF ALU example, the basis for the Generator Tutorial. The tutorial demonstrates, to a user with a limited amount of UVM experience, how to successfully create a UVMF verification environment basically from scratch. This creation of a UVM environment, via Python or YAML scripting, is remarkable given 1) the vast amount of UVM factory files created to support a complete UVM environment, and 2) the mere fact that most UVM work has been traditionally based on an [existing] architected UVM template, of some sort created by somebody, to start with. Instead, we are starting with no testbench code of any type.
So, to go from scratch to an executable UVM environment with UVMF automated scripting allows possibly 80% of the bulk of the UVMF code to be in place in short time. However, getting the rest of the custom code in place for your DUT to see any activity takes much more time, as the “smarts” that gets contextual stimulus to the DUT pins must be understood and integrated. For example, the default stimulus provided by the generator tutorial, initially, results in a not quite complete path to the top test control that would allow customized stimulus insertion. Instead, the stimulus is generated further downstream via UVM randomization, which works absolutely fine for this simple ALU example.
If your DUT requires specific (non-random) stimulus patterns you must either create this at the BFM driver site (not good UVM practice), or allow data manipulation from somewhere upstream of the BFM within the UVM architected test, sequences, and/or transactions. Again the focus of this article will be that of inserting manual stimulus control at the top test control level.
TOP TEST CONTROL STRUCTURE
The Figure, Top Test Control Structure on the following page, depicts the customized implementation for manual manipulation of the tutorial’s ALU A and B input stimulus from the top test. The top green block, alu_manual_test, is the new extended test with SystemVerilog assignments to the stimulus, implying manual top test control. The connected blue blocks, alu_manual_sequence and alu_in_manual_sequence, are the two new sequences required to get the manual stimulus from the top test to the existing alu_in_transaction. Thereon, this transaction terminates at the target ALU Driver Agent, in particular the “alu_driver” which then allows a proxy access to the “alu_driver_bfm”, within the same agent, to get stimulus to the DUT I/O.
Of particular note:
- Since there is no DUT clock or data strobe of any sort, a finite “wait” delay is inserted in the alu_manual_sequence which provides a mechanism for data synchronization
- It requires two contiguous sequences to get stimulus from the top level alu_manual_test, through both manual sequences, onto the alu_in_transaction, and finally to the ALU Driver Agent. This is primarily because the UVMF inherent architecture, which is python template generated as UVMF, consists of two separate distinctions of “project_bench” and “verification_ip” containers. This is readily evident in the directory structure naming convention as observed @ generator_tutorial/uvmf_template_output/project_benches/verification_ip
Figure 2 - Top test control structure
CREATING THE NEW TEST
Creating a new UVMF test actually becomes quite easy by “extending” the top test. The basics of doing this allows the original test class constructs and attributes to be extended automatically to the new test. The technique being demonstrated here will involve copying/modifying an existing test that, itself, has already been extended from top_test. The following is the method to create our new test:
- Copy alu_random_test.svh to alu_manual_test.svh and make the following changes to the new test.
- Change the text “random” to “manual” throughout the file.
- Create the manual sequence handle. Later you will create the alu_manual_sequence, however here you must create a handle to it to use as a pointer within the test run_phase.
class alu_manual_test extends test_tip;
`uvm_object_utils ( alu_manual_test );
//Create manual sequence handle
- Ensure that the alu_bench_sequence_base has been over-ridden with the alu_manual_sequence in the build phase.
virtual function void build_base (uvm_phase phase);
endfunction // build_phase
- Add the task run_phase. The task run_phase must first create the alu_manual_sequence which can then be used to assign manual stimulus to the “a” and “b” inputs of the ALU. In this example, a simple Verilog “repeat” statement, with an incrementing stimulus and UVM start command allows the run_phase of the test to start, run, and complete via the UVM raise_objection and drop_objection constructs.
//Add the UVM run phase to allow manual manipulations of ALU a & b inputs
virtual task run_phase (uvm_phase phase);
phase.raise_objection (this, "Top Test");
`uvm_info(get_name (), "Starting alu_manual_test", UVM_LOW)
// Create the top manual sequence to alu_manual_sequence which drives the ALU a & b inputs.
alu_manual_seq = alu_manual_sequence #(8)::type_id::create ("alu_manual_seq", this);
// Initialise the ALU a & b inputs
alu_manual_seq.a = 0;
alu_manual_seq.b = 1;
// Manually manipulate values for a & b start the sequence
// The op input remains randomized downstream in alu_manual_sequence
alu_manual_seq.a = (alu_manual_seq.a) +1;
alu_manual_seq.b = (alu_manual_seq.b) +1;
- Add the new file name to alu_test_pkg.sv file. This is a simple `include statement of the file name so it gets included in the compile.
CREATING THE NEW BENCH SEQUENCE
Creating a new UVMF project bench sequence, similar in process to the new test created in the previous section, is quite easy by “extending” the top bench sequence. The basics of doing this allows the original project bench class constructs and attributes to be extended automatically to the new sequence. The technique being demonstrated here will involve copying/modifying an existing project bench sequence that, itself, has already been extended from alu_bench_sequence_base. The following is the method to create our new project bench sequence:
- Copy alu_random_sequence.svh to alu_manual_sequence.svh and make the following changes to the new sequence.
- Change the text “random” to “manual” throughout the file. Importantly this results in creating the alu_in_agent_manual_seq at the top of the task body.
- 3. Add the logic “a” and “b” declarations for this sequence prior to the task body.
// Add logic for the sequence variables, inputs to the ALU
logic [ALU_IN_OP_WIDTH-1:0] a=0;
logic [ALU_IN_OP_WIDTH-1:0] b=0;
- Add the ALU input logic assignments to the new sequence and default to only one start per sequence. This allows the repeat statement in alu_manual_test.svh to control the length of the simulation.
// Assign the ALU a & b inputs
alu_in_agent_manual_seq.a = a;
alu_in_agent_manual_seq.b = b;
// Default to only one start per sequence
repeat (1) alu_in_agent_manual_seq.start(alu_in_agent_sequencer);
- Add the new file name to alu_sequences_pkg.sv file. This is a simple `include statement of the file name so it gets included in the compile.
CREATING THE NEW VERIFICATION IP SEQUENCE
Creating a new UVMF verification IP sequence, similar in process to the new bench sequence created in the previous section, is quite easy by “extending” the top verification IP sequence. The basics of doing this allows the original verification IP class constructs and attributes to be extended automatically to the new sequence. The technique being demonstrated here will involve copying/modifying an existing verification IP bench sequence that, itself, has already been extended from alu_in_sequence_base. The following is the method to create our new project bench sequence:
- Copy alu_in_random_sequence.svh to alu_in_manual_sequence.svh and make the following changes to the new sequence.
- Change the text “random” to “manual” throughout the file. Notice that you do not have to create another sequence since the downstream UVMF element becomes the existing alu_in_transaction.
- Add the logic “a” and “b” declarations for this sequence prior to the task body.
// Add logic for passing ALU data in
logic [ALU_IN_OP_WIDTH-1:0] a=0;
logic [ALU_IN_OP_WIDTH-1:0] b=0;
- Add the ALU input logic assignments to the alu_in_transaction to get the manual stimulus to the alu_in_driver.
// Assign the manual data, passed from the top alu_manual_sequence
// This assigns the a & b data to the alu_in _driver
areq.a = a;
areq.b = b;
- Add this sequence to the alu_bench_sequence_base.svh file (as it is used by the project bench sequences upstream) so they are available via extension of the project bench base sequence.
// add verification IP manual sequence
typedef alu_in_manual_sequence alu_in_agent_manual_seq_t; alu_in_agent_manual_seq_t alu_in_agent_manual_seq;
- Add the new file name to alu_in_pkg.sv file. This is a simple `include statement of the file name so it gets included in the compile.
MODIFYING THE SIMULATION MAKEFILE AND RUN
The following modifications are required, of the sim/Makefile, in order to run Make to build and execute the UVMF simulation with the new alu_manual_test in your area.
Define the path to your QuestaSim UVMF home area. Note this requires the versions, minimally, that are shown for both Questa (10.7b) and UVM_Framework (3.6g). Note that the original code (commented out) searched for the UVMF area with wildcards, but does not specify a UVMF version, thus the export of a hard path to ensure version compatibility.
Set the TEST_NAME variable to the new test.
# UVMF library directory:
# This variable points to the UVMF release where uvmf_base_pkg_directory resides.
# This variable points to the release code that is not user modified.
# This variable allows for the UVMF release directories to reside independent of project related verification_ip and project_benches directories.
# This code below looks "upward" for directory starting with UVMF_* and returns first match for use with the release examples.
//UVMF_HOME ?= $(firstword $(wildcard $(addsuffix /UVMF_*,. .. ../.. ../../.. ../../../.. ../../../../..)))
export UVMF_HOME ?= C:/questasim64_107b/examples/UVM_Framework/UVMF_3.6g
# Set test case specific Variables
TEST NAME ?= alu_manual_test
This completes the modifications and now the simulation can be run by executing, in the sim directory:
- “make cli” -run with out Questa GUI
- “make debug” -run with Questa GUI
MODIFIED/NEW FILE LIST
The following is a list of the generator_tutorial files that were either modified or added to complete the top test control functionality.
A. Modified Files:
B. Added (New) Files:
Becoming proficient at architecting a UVM (i.e. no “F” appended to this acronym) environment requires an extremely steep learning curve by all accounts, even for those folks who have a strong background in traditional SystemVerilog testbench design. With Mentor’s UVMF template generation methodology, a UVM environment is readily achievable for Verification Engineers that may have little to no experience in UVM technology, but possess the architectural mindedness for good testbench design from the onset. At this point, it becomes a reasonable and manageable task to put in place the “smarts” to turn a UVMF factory implementation into a working DVE which has bonified UVM structure.
The “front end” customization presented in this article can be directly applied to completing the other noted parts of the UVMF environment, with help from Mentor’s examples and documentation. This may take some further experimentation (simulation breakpoints and inserting experimental code cannot be emphasized enough here!), as was necessary in the given scenario that resulted in the basis of this empirical article. It is surprising to hear of large, established corporations investing incredible time and money into attempts at creating UVM by hand, and ultimately failing.
UVMF can get you 80% there (well maybe the code base anyways), and from there it is truly within the grasp of the Verification Engineer to create a customized and useful UVMF environment.
 “UVM_Framework_Users_Guide.pdf”, Rev 3.6g_0, Mentor, A Siemens Business. Located at: @questasim64_10.7b/examples/UVM_Framework/UVMF_3.6g/docs
 “ALU_UVMF_Step_By_Step_Guide.pdf”, August 2017, Mentor, A Siemens Business. Located at: @questasim64_10.7b/examples/UVM_Framework/UVMF_3.6g/docs/generator_tutorial
 “Generator Tutorial”, a Mentor UVMF example demonstrated in Reference 2, located at: @questasim64_10.7b/examples/UVM_Framework/UVMF_3.6g/docs/generator_tutorial
Back to Top