Atomic actions are capabilities of functional blocks, but how do these things get done? That is the responsibility of the “exec” block.
How many times have we heard the old adage “If it sounds too good to be true, it probably is”? It almost becomes second nature to dismiss new ideas when the gains are talked up but the details are hidden. This is a trap that we find ourselves in at times with the Accellera Portable Stimulus Standard (PSS). There are so many things to be excited about that we sometimes forget to talk about the more mundane aspects of the technology.
We shall fix that in this blog and get into some of the details necessary for this technology to work.
In my first two blogs (“Filling in the Blanks” and “Concurrency and Schedules”), I talked about how a model describes aspects of the control and data flow present in a system. Verification synthesis can fill in the gaps of partial specifications and create complex schedules that stress a design. The creation of scenarios is the front end of the verification synthesis process. This is the fun and exciting piece of the technology because it uses abstraction and automation and adds productivity layers that verification teams have never had before.
I will initially add to the wonder by saying that verification synthesis also makes retargeting to different execution technologies possible. In fact, this is the very reason why Portable Stimulus was created and how it got its terrible name.
The name is terrible in many ways. First, PSS is not just about stimulus; it is a language used to define a model that captures stimulus, response, and coverage in a unified manner. This is what makes it the first true verification model that the industry has ever had.
Second, the stimulus created by a synthesis engine is not portable. The synthesis engine takes the model and can target multiple execution environments, but once created, the testcase can only be executed in conjunction with that environment. What PSS does bring is portability of models between vendors.
The retargeting of a scenario to an execution engine is the back end of the synthesis process, and this is where a lot of the hard work gets done. Accellera’s DVCon training session used the diagram shown below to illustrate aspects of the tool flow.
It’s important to note that the depiction above is not necessarily how individual tools that implement the PSS standard actually work, but it does serve to demonstrate the multiple stages of the flow. They call the front end of the process compilation and constraint solving (although the Breker tool does a lot more than that), while the back end of the process is called test generation.
In previous blogs, we talked about the concept of atomic actions. These are capabilities of functional blocks, such as sending a packet of data or performing a DMA transfer. But how do these things actually get done? That is the responsibility of the “exec” block.
Inside the exec block, the user must write code that describes how a target would make that action happen. We can get into the details of that in another blog. For every target environment, you may need to write another exec block, and then at compile time, you can conditionally include the appropriate code. The high-level functionality of each exec block is the same, but how each block implements its functionality may be very different. The problem with this is that the end user could well end up writing a lot of code that should be provided or generated automatically. At Breker, we have gone out of our way to reduce this largely unnecessary effort as much as possible.
Breker prefers a different mechanism, which is to use the hardware/software interface (HSI). For example, if the target is a simulator, the exec block has access to back-door memory access capabilities. These can be used to set up the design, put in place any necessary data, and then trigger an action. They may also use the same mechanisms to get results back into the test environment for result checking.
But what if you now want to target real silicon? There are no back-door memory access mechanisms in silicon, or at least there shouldn’t be! Instead, you may decide that the necessary data is to be transferred through a UART port. The exec block would probably contain a software routine to get or drive the necessary data from that port. You may also want to use pieces of production software. This is where the HSI layer comes into play, allowing you to select which code you want to use.
For example, drivers may be installed, and these drivers could be used for data transfer rather than writing bare-metal code. The Breker implementation makes available a library of services that users find helpful in building this kind of capability in ways that reflect what the eventual software may look like. These include memory allocation procedures, interrupt processing, etc., and all parts of the HSI layer that Breker provides, even though these did not make it into the 1.0 version of the standard.
It may be helpful to show our first snippets of PSS code at this point, again using a slide from the DVCon training course, as illustrated below:
Primitive actions performed by an IP or reusable element are contained within a
component. The action
hello_world_a contains an
exec_body that defines the implementation. When the back end of the synthesis process runs, it transfers the code in the exec block into the code that is going to be executed. In this case, the code becomes part of a UVM testbench and is inserted in the task body.
Now you see that some of the magic actually comes down to the user doing part of the work, telling the tool exactly how to make the magic happen.
In the next blog, we will look at ways in which PSS can enhance your existing UVM flow and the benefits that would result. As always, please reach out to me with any comments or questions if clarification is required.