Wednesday, 5 June 2013

Test Bench Control Part Three

Why Integrate Python?

Or Ruby or Lua ...

I chose Python as it is the most modern scripting language that I am familiar with. And powerful, popular with good library support. It could be Ruby, Lua or Javascript (Javascript is an interesting choice - perhaps that's for another blog post!).
The motivation here is three fold
  1. To integrate as much of the test framework scripting as possible as close to the simulation as possible. Executing script code within the scope of the test bench gives the script direct access to the structure of the test bench and the ability to control values within. Warming memories and registers can now be performed directly without the requirement of creating hex dump files and reams of plusargs.
  2. To integrate common message/logging infrastructure across the simulator and script to retain as much of the message semantics as possible (think file name, line number, scope, time/cycles). There is then no difference in an error generated by the script or the simulation as they both pass through the same message logging library. We do not need to regular expression parse text files to find messages and extract information we had before it was all flattened into text.
  3. To make scripting within the simulation environment useful again. Built in TCL interpreters and simulator specific commands have been holding this back since, well - forever.
On the first point we can import the verilog VPI into our scripting language and add a test prologue and epilogue to be run before and after the simulation (we can use the VPI call backs cbStartOfSimulation and cbEndOfSimulation). In these routines we can poke values into the simulation and read them out afterwards, a use case might be pulling relevant sections from an ELF file then warming caches and data memory. Similarly at the end of a simulation memories can be inspected for expected golden values. Should these values not match then an error can be raised via the second point - common messaging infrastructure. So should anything go awry during simulation, where ever it is detected, be it script, Verilog or C++ all messages will be treated equally and reported accurately without any kludgey regular expression parsing of output streams. There is another important advantage here too, if we have test bench monitors that are reporting messages we can filter these out too. We can filter just the ones we're interested in to see what's going on in one or a few. The advantage here over having multiple output files for each instance is that the messages will be automatically sequentially interleaved. (Filtering by scope is not currently part of the example, but could be easily added.)
Finally I believe there are many advantages to using Python (or Ruby or Lua) over Tcl (or indeed Perl) that makes this infrastructure architecture compelling. Religion and arguments about relative performance aside, the newer languages are built on the foundations of Tcl and Perl and as such they are everything Tcl and Perl are and more.
There are also advantages in gluing the performant pieces of the test bench together with a scripting language, the foremost is that recompilation is not required when an edit is made to those portions of the code. As long as scripts are only called at the beginning and end of the simulation we can trade off recompilation against interpretation to increase the edit-debug iteration frequency. Scripting languages are often more concise when dealing with option parsing or regular expressions, and can be much more lightweight when used to e.g. interface with databases or the file system when compared to C++. If high performance is not required then dynamically typed script code will almost always be more concise as well as quicker to write and debug.

Importing APIs with SWIG

SWIG is the Simplified Wrapper and Interface Generator. Put simply it takes a C or C++ header file and generates a wrapper around it so it can be used in the scripting language of your choice. I find that this wrapped API is still a little rough around the edges, so I then wrap it again with a thin veneer to make it match the scripting language idioms more closely. This process does introduce some compute overhead, but the idea here is that we execute this code very infrequently just to set things up, so the performance is not really of any consequence in the scope of the entire application.
The next two blog posts will look at importing the Verilog VPI and then a simple messaging library into Python using SWIG. After we have done this we can use both together.

Note on ctypespyrex

A quick mention of the Python library ctypes as a replacement for SWIG. If a dynamic library is available this can be a very quick way to get going with it in Python, but it's not relevant here for the VPI. Also pyrex which could be used instead of SWIG in this instance.

No comments:

Post a Comment