- Mark Peryer - Mentor Graphics
Writing effective stimulus in UVM can prove to be challenging for various reasons, but not knowing about the relevant coding design patterns should not be one of them. There are various alternative techniques for writing sequences and choosing the right approach requires mastery of several styles. This paper describes seven common sequence design patterns which should prove useful to all UVM sequence writers. These patterns can be used stand-alone or combined to solve practical stimulus generation problems using UVM sequences.
The UVM sequence is designed to be a transitory, or short-lived, class object that is constructed; used to generate stimulus; and then dereferenced, pending garbage collection. It contains a body() method, implemented as a SystemVerilog task, which is called when the sequence is started using its start() method. As the body() method executes it either generates and shapes sequence items, or it creates and starts other sequences. A sequence communicates with a driver via the sequencer component using sequence items.
In practice, most sequences are quite simple, generating a few sequence items before completing. However, more complex stimulus generation requires the use of more advanced techniques. The purpose of this paper is to describe a number of common sequence design patterns.
The main purpose of the UVM sequence is to generate sequence_items and to send them to a UVM driver component using an API that is implemented in the UVM sequencer component.
A. The sequence_item
The sequence_item is an object that contains transaction level data that the driver is responsible for interpreting and converting into pin level activity. An example sequence_item is shown in Fig.1. This particular sequence_item contains data items that can notionally be used to describe a bus interface transaction and will be used in most of the design pattern examples that follow. It contains stimulus fields which are rand so that they can be randomized and response fields which are not. Generally, the sequence_item also contains a set of convenience methods which can be used to copy(), clone(), compare(), print(), convert2string(), pack() and unpack() the transaction, but these have been omitted from the example for the sake of brevity.
B. The Sequence
In its simplest form, a sequence creates a sequence_item, assigns values to its data fields and then sends it to the sequencer. The code example in Fig.2 shows how this is typically done. The active part of the sequence is the body() task method. In this method, the sequence_item is created, then the blocking start_item() method is called which returns when the sequencer is ready to send the sequence_item to the driver. In this example, the sequence_item is then randomized and sent to the driver using the blocking finish_item() method. The sequence ends when the driver unblocks the finish_item() method.
View & Download:
Read the entire Seven Separate Sequence Styles Speed Stimulus Scenarios technical paper.