This article highlights the use of list pseudo-methods constraining the content of lists, which is relatively new and offers a lot of power in terms of modelling, performance, and debugging.
Ethernet-based communication is getting more pronounced today and will continue to do so in the future. This increases the need to be able to verify devices that are capable to handle specific bandwidth requirements. Shaping constrained random Ethernet traffic can be quite complicated, especially if a specific set of requirements needs to be properly exercised.
In this example, the requirements are:
- Generate a stream of Ethernet frames that fits within a given bandwidth
- Ethernet frame sizes have to vary between a minimumand a maximum frame size
- Ethernet framesizegeneration shall be independentfromotherEthernetframeparameters
The first requirement refers to bandwidth. In this context bandwidth is defined as the number of frame bytes per time window. The second requirement refers to boundaries that are applied to each frame. Each frame’s size needs to be in between a given minimum and maximum size. The third requirement indicates that the generation of the frame sizes is independent of other frame parameters and can be determined in a separate variable.
Based on these requirements, we can now think about how to model the constraints. In a first step, we need to understand the data structures involved. Since the requirements state that we want to generate several frames with varying sizes, without having to generate the whole frame upfront, the best fit for such a model is a list of unsigned integers (to represent the frame size).
Furthermore, we might need this kind of constraining several times throughout our testbench, and we might need to do this kind of constraining with different bandwidth values, minimum and maximum frame sizes. In order to achieve this, it makes sense to encapsulate this constraining process within a method returning a list of unsigned integers.
In the following code snippet you’ll see:
- The data structures to hold the frame sizes (list1, list2, and list3)
- The constraint block to assign the various frame sizes
- The value-returning method containing the requirement constraints
- A post_generate block for message output
Looking at the gen-result-keeping block, you’ll notice that the requirements are almost plain text readable in the first three constraints, which facilitates maintenance and debugging.
However, there are some gotchas you should be aware of:
a) When applying list constraints, you need to keep in mind that the list size will be generated before its items. This means that the list size generation and the list element generation is handled in two separate CFSs and there is no backtracking between these two CFSs, which is why the fourth constraint in this gen-result-keeping block is needed.
b) Due to backwards compatibility, using list pseudo-methods such as min_value() and max_value() in constraints currently yields the warning DEPR_UNIDIR_LIST_PSEUDO_METHODS_141, which in our example will lead to a GEN_NO_GENERATABLE_NOTIF error if the bidirectional solving is not enabled.
Additional new generative list pseudo-methods that also support bidirectional solving are:
- all_different( item: exp, bool_exp: bool ): bool (conditional)
- and_all( exp: bool ): bool
- or_all ( exp: bool ): bool
Bidirectional solving of the above mentioned list pseudo-methods was first introduced in Specman 14.1. Enabling the new list constraints bidirectional solving can be done directly in Specman.
- conf gen -bidir_list_pseudo_methods=ALL_SUPPORTED_SINCE_141
or using Incisive Runner (irun)
- irun -snset "conf gen -bidir_list_pseudo_methods=ALL_SUPPORTED_SINCE_141" ...
Note that bidirectional solving will be enabled by default for Specman versions 14.2 and above.
Thank you for reading and happy constraint coding,
Daniel Bayer