Software Model Interface
© Copyright 2000-2001 Adrian Lewis


SMI Home
Why SMI?
Documentation
Download
Platforms
Future
Support

   

Why SMI?

This page presents reasons for incorporating SMI into your simulation environment. It examines some of the typical implementation strategies used to create hardware simulations; highlights their shortcomings, and describes the advantages to be gained by using SMI:

Modeling with Verilog

You're using Verilog to implement your design, why not use Verilog to create hardware models? After all, no extra tools or knowledge base is required. The problem is that Verilog lacks many important features supported by programming languages like C++. Verilog suffers from poor file handling and poor inter-module communication; it lacks data types and structures; it does not support recursion or object-orientation. As a result, Verilog models are often significantly harder to write, run slower, and have fewer features than hybrid models.

An alternative to implementing models entirely in Verilog is to implement them almost entirely in C or a similar programming language; the hardware model communicates with the Verilog simulation using the PLI. However, standard programming languages make poor simulation languages as they often lack a concept of time or concurrency. Choosing this alternative substitutes the disadvantages of Verilog as a programming language for the disadvantages of programming languages as a simulation language.

The ideal solution is to create models using a balanced implementation. A hardware component, written in Verilog, performs the tasks Verilog is good at; a corresponding software component, written in a programming language, performs the tasks programming languages are good at. The hardware and software components communicate using either the Verilog PLI or SMI. The resulting hybrid model exploits the strengths of both programming environments. The next section shows the advantages of the SMI library over the Verilog PLI.

Modeling with Verilog with the PLI

The Verilog PLI allows users to incorporate programming language code into their simulation. There are three standard PLI implementations; "tf", "acc" and "vpi". Not all simulators support all PLI implementations or even full PLI implementations, so portability of PLI based code can be a major issue. SMI can be built to sit on top of either "tf" or "vpi" PLIs and only uses a small sub-set of the routines provided by these PLIs.

As the PLI was designed to be a general interface, each implementation provides a large number of low level routines for passing data between C code and the Verilog simulation. The large number of routines make learning a PLI implementation a long process. The low-level nature of the routines makes creating models with the PLI an arduous task. SMI focuses on hardware modeling. It provides the user with a small number of high level routines and hence is easier to learn and to use.

The simplest method of using the PLI to interface C to Verilog is to use the PLI to create Verilog system tasks implemented by a C subroutine. However, using subroutines to build hardware models not a straightforward task.

  • Several system tasks make be required to implement a model which implies that the C subroutines implementing the system tasks share a common data structure.
  • A model may have multiple instances, each with their own data structure.
  • A model may need to coordinate it's activities with other models or with a test coordination script.
  • A model may be easier to implement if it has its own thread of execution.

SMI addresses all of these requirements freeing the user to concentrate on modeling rather than grappling with the PLI.

Using vendor-supplied models

Why write your own model or modify a vendors model if the vendor has supplied a working model?

  • The vendor model may be protected or scrambled which makes debugging any problems encountered with the model much harder.
  • The vendor model may be implemented inefficiently using lots of memory or runtime. For example, large Verilog memories and models that are actually gate level implementations.
  • The vendor model may not have the test features you want. For example, memories than can't be pre-initialized or dumped to a file.
  • The vendor model may be too accurate for functional test! For example, a PLL model that takes second of simulation time to frequency lock or processor models that run machine code when all you need is external bus transactions.

SMI was designed to make implementing models and modifying vendor models a quick and simple task. Why limit yourself to the features provided by a vendor?

Implementing memory models

Practically all designs of any size contain or interface to some kind of memory. It is not uncommon for library or part suppliers to provide Verilog memory models of the memory cells and components they supply. However, although these memory models may function correctly, they often suffer from several shortcomings.

  • Large Verilog based memories are very slow to simulate and require large amounts of simulator memory.
  • Testing features are limited to reading and writing the memory contents to text files.
  • Dynamic coordination between a test process and the memory model is impossible (or at least fraught with peril).

SMI can be used to construct memory models free these the drawbacks. SMI can also be used to adapt memory models supplied by vendors, removing the Verilog memory and replacing it with an SMI model. This technique can be used to create memory models with the interface and timing specifications supplied by a vendor but with the flexibility and performance of an SMI memory model.

Implementing processor and bus models

Processor and I/O bus models provide one of the most compelling reasons for using SMI. Thanks to the prevalence of stand-alone and embedded micro-processors in modern digital design, nearly all designs either contain or interface to one or more processors. It is not uncommon for library or part suppliers to provide Verilog models of the processor cells and components they supply. However, although these models may function correctly, they may often suffer from several shortcomings.

  • If the source code of the model is encoded or protected, then debugging the models operation is hindered as none of the internal registers are visible.
  • If the model operates on binary code and data and if the model does not support symbolic debugging, then debugging the test code can be difficult.
  • If the model contains memories models then they may suffer from the disadvantages described in the previous section.
  • If the model is cycle accurate, it may be difficult to generate the correct timing for a particular sequence of stimuli necessary to perform a specific test on the design under test.
However, vendor-supplied cycle accurate models of processors embedded in the design under test must be used to generate test vectors.

Implementing a processor model entirely in Verilog (i.e. without using the PLI) implies that all test code is either written in Verilog or read from a file. The PCI bus model from Synopsys is a good example of this type of Verilog model. If all the test code is written in Verilog, typically in terms of Verilog task calls, then each test generates a simulation executable, which consumes both time and disk space. If the test code is read from a file, then the sequence of operations is fixed by the order of commands in the file, which is very inflexible. In either case, the code can only be used with the hardware simulation. It cannot be easily converted into real processor code or binary code used by the vendors processor model.

Ideally a processor model would accept the same C source code used to generate the binary code required to run on the vendors processor model and the physical processor hardware. The model would allow the test code to be symbolically debugged as it was running, or more accurately, as it was being simulated. The test code could then be debugged in a friendly environment before converting it into binary for the generation of test vectors or to run on the physical hardware. In addition, any code running on the physical hardware that generates an error could be ported back to the simulation environment where the cause of the error could be tracked down. SMI provides all the facilities required to construct processor and bus models that incorporate these features.

Checking expected responses

A full implementation of a hardware component is a description that be synthesized into manufacturable circuitry. A hardware model is often just a simplified implementation that simulates like the full implementation but is unsynthesizable. However, hardware models just as often contain additional functionality used to test the design in a variety of scenarios. Hardware models may be used to apply test stimuli and to collect the designs response.

A standard test strategy uses sets of files to provide stimuli for hardware models. Another set of files contains data corresponding to the expected response of the design. During simulation, a hardware model will read and apply stimulus data by reading its stimuli file. It will concurrently collect and compare expected response data by reading its response file. An individual test scenario is embodied in a set of stimuli and response files.

A file based test strategy requires that all stimuli and response files be generated before the simulation begins. Hence the exact response data and its sequence of generation must be known even though the design may not be specified to this level of detail. This requirement can be extremely difficult to fulfill. For example, a network router may be specified to route or drop an incoming packet within a specified time period. However, the exact order in which the packets enter and leave the router may not be specified and may be very difficult to predict. Generating the response files for this kind of scenario can be a wasteful and time consuming task.

SMI allows the design to be verified dynamically using test code rather than by files. The test code runs in its own process and each model is implemented by a C++ object which is part of the test code process. By called methods provided by the model objects, the test code can dynamically coordinate the application of stimuli and collection of response data performed by the models. The use of test code is a far more flexible and efficient test strategy than the use of files.