Validate Assertions in Packet-Based Protocol Designs Using UVM Callbacks
Assertions bring immediate benefits to the entire design and verification cycle. To use assertions effectively in the verification cycle, they need to be exercised for checking legal design behavior and must fire when illegal behavior is encountered in the design.
When a large number of assertions need to be validated for firing under illegal circumstances, a callback mechanism is particularly effective for creating these scenarios. That’s because they require minimal updates to the testbench environment and minimize the effort to create complex scenarios for validating the assertions.
By definition, a callback mechanism, or function, is a “call-after” function that alters the intent of the original function call. Callbacks are a common mechanism used in functional verification to modify the original content of a sequence item to induce a desired scenario. This enables more dynamic and fine-grained control in selecting which particular sequence item gets corrupted and, in a test, how many such corruptions occur in order to stress test the design. Since callbacks allow for the easy creation of nuanced and complex stimulus creation, they’re instrumental to assertion verification.
This article describes how callbacks implemented in verification IP can be used for assertion validation in designs using PCIe and other packet-based protocols.
Assertion verification is usually an integral part of the verification IP development cycle (Fig. 1). The first step involves coding the assertions. The second step validates the assertions by creating scenarios that fully exercise the assertions to ensure they don’t fire under intended design behavior and do fire under erroneous scenarios.
Callbacks can be very beneficial in the scenario-generation step since the verification engineer doesn’t have to write additional tests. Instead, they enable callbacks to modify the original stimulus to create interesting scenarios. This is achieved by simply extending the callback class to override the virtual method:
do_callback(...)that gets called when a sequence item is executed by the bus functional model (BFM). This is particularly useful in packet-based protocols, such as PCIe, where packet fields need to be corrupted and callbacks provide fine-grained control to do so.
The validation engineer’s job is to make sure that the assertions are validated in every relevant scenario. Callbacks can be of extreme importance when assertion validation is carried out by manipulating the fields of a sequence item or by initiating a sequence item in a state in which it’s not allowed. Callbacks speed up assertion validation by providing the entire structure for such manipulation in a UVM testbench, with minimal updates and no interaction with the existing sequences responsible for generating the sequence items.
For a layered protocol like PCIe, where communication between the transmitter and receiver elements takes place via structures known as packets, the use of callbacks for assertion validation significantly improves efficacy. Using verification IP, the packet information can be modified via callbacks and all packet-based assertions can be easily verified by making use of this mechanism. Now let’s look at a scenario from each of the transaction, data link, and physical-layer packets.
Case 1: Transaction-Layer-Based Callbacks
The high-level transactions occurring at the device core are known as transaction layer packets (TLPs). Verification IP, such as Questa Verification IP, allows all fields of a TLP (both request and completion TLPs) to be altered. If users want to validate an assertion related to the fields of a TLP, they can simply do so by corrupting the TLP fields via a callback.
For example, the PCIe protocol states that for a request of “length = 1 DW,” the value of the Last Byte Enable field should be zero; where Last Byte Enable is the Byte Enable value for the last DWORD of the request. In simulation, if users want to inject this error to every Memory Write packet of length 1 DW, then they may do so as illustrated in Figure 2.
Case 2: Data-Link-Layer-Based Callbacks
Data link layer packets (DLLPs) are used for a variety of purposes, such as ensuring the integrity of TLPs, flow control, and power management. Just as for TLPs, callbacks can be used to inject errors in DLLPs. For instance, lcrc is used to check the data integrity of TLPs and DLLPs. lcrc is appended in the TLP at the data link layer (DLL). If the value of the lcrc attached with a packet isn’t the same as the calculated value, then it’s a protocol violation. This incorrect behavior, or assertion firing, can be verified (Fig. 3).
Case 3: Physical-Layer-Based Callbacks
Perhaps the most efficient use of callbacks comes from modifying ordered set fields. In the cases of DLLPs and TLPs, a packet can still be executed via a sequence once linkup is achieved. But using a sequence to inject an error into an ordered set before linkup can be more convoluted and more susceptible to errors because the ordered set rules change with each LTSSM (link training and status state machine) state.
Callbacks, on the other hand, allow the user to inject an error in a much more controlled way. For instance, if a control SKP ordered set is to be sent in place of a TS2 OS, one can easily use callbacks. Hence, this invalid protocol scenario can be easily validated via callbacks (Fig. 4).
As can be seen, when a large number of assertions are to be validated, callbacks save time by making sure the engineer doesn’t have to code a new sequence for each scenario. Callbacks allow for the creation of nuanced and complex stimulus with ease and, thus, are instrumental for assertion verification.
Akshay Sarup is a Product Engineer for CXL and PCI, and Mark Olen is the Product Marketing Group Manager for the ICVS Division at Mentor, a Siemens Business.