Overview
A hardware emulation platform, such as Mentor Graphics' Veloce, comprises a solution built upon specialized hardware to deliver high-performance model execution and provide orders of magnitude performance improvement over a traditional software simulator. For Veloce, the specialized hardware includes custom IC technology optimized for the needs of emulation and yet the simple use mode of software simulation.
Since models are compiled into hardware, they must be synthesizable. UVM testbenches rely heavily on object-oriented coding techniques, using SystemVerilog classes and other constructs that are not synthesizable and cannot be executed on an emulator - they must be executed on a software simulator. By combining software simulation for those parts of a testbench that are not synthesizable with hardware emulation for those parts that are synthesizable, you can gain much of the performance benefits of emulation while preserving the power and reuse benefits of UVM-based test environments.
This article describes a co-emulation (a.k.a. co-modeling) approach to writing testbenches that maximizes reuse by enabling truly single-source, fully IEEE 1800 SystemVerilog compliant testbenches that work interchangeably for both simulation and hardware-assisted acceleration. The content provided here is a basic introduction, based predominantly on the Mentor Graphics whitepaper "Off to the Races With Your Accelerated SystemVerilog Testbench". You should refer to this paper, which also appeared in DVCon 2011, to gain a deeper understanding of the requirements and solutions presented.
-
Requirements
Executing a test using co-emulation, where a software simulator runs in tandem with an emulator, presents unique challenges. An emulator is a separate physical device that is executing behavior completely independently from the software simulator. It is connected to the simulator using a transaction-based communications link. This has the following implications:
- The synthesizable code that is to be run on the emulator must be completely separated from the non-synthesizable testbench code, placed in separate physical files as well as separate logical hierarchies. These two hierarchies are called the "testbench domain" and the "HDL domain".
- The testbench components that bridge the gap between the test environment and the physical environment - i.e. the so-called transactors like drivers and monitors - must be split into timed and untimed parts, and the parts placed in their respective domains. The untimed portion of each transactor resides in the testbench domain and becomes a proxy to the corresponding timed part in the HDL domain, referred to as BFM. The HDL BFM and its testbench proxy must interact at the transaction level over the emulator-simulator communications link.
- Any timing control statements including #-delays, @-clock-edge synchronizations, and fixed time-interval wait statements left in the testbench environment must be removed, as they impede co-emulation performance. As deemed necessary, these must be remodeled using clock synchronous behavior in the timed HDL domain.
- The link between the simulator and emulator is a physical communications link that deals in packets of data as opposed to transaction object handles. A mapping between packed data packets and transaction objects may therefore be required typically for object-oriented testbenches. Furthermore, in order to achieve highest possible performance the amount of traffic on the physical link must be minimized or optimized.
The above statements can be boiled down to the following three main requirements:
- Verification code must be completely untimed, i.e. be free of explicit time advance statements. Abstract event synchronizations and waits for abstract events are allowed.
- Untimed verification code must be separated from timed code into two domains.
- No cross-domain signal or module references are allowed.
For more detail on these and other requirements, refer to the whitepaper "Guidelines for Crafting XLerated SystemVerilog OVCs" (note, this paper is still OVM-based, but its contents continue to be largely applicable to UVM).
Methodology Overview
The goal here is to describe a methodology that not only meets the above requirements for co-emulation, but also does so using a single-source codebase, meaning that no code changes are needed to perform tests using either software-only simulation or co-emulation.
The first requirement to address is that there must be two separate logical hierarchies - one to be compiled into the emulator, and one for the testbench environment. This can be accomplished using a "Dual Top" technique. Click here for a general overview of this technique, and here for applying the technique to co-emulation.
Once two separate domains are established, the transactors of the testbench must each be split into an untimed transaction-level proxy component in the testbench domain (e.g. a SystemVerilog class like a uvm_component derivative) and a synthesizable BFM in the HDL domain (e.g. a SystemVerilog interface). The two parts are to use a collection of user-defined tasks and functions - effectively representing transactions - to implement their required transaction-based communication across the emulator-simulator boundary. An HDL BFM interface implements synthesizable tasks and functions to be called from its proxy via a virtual interface. Conversely, the BFM interface may initiate method calls back into its proxy via an object handle also referred to as back-pointer.
Lastly, since code in the testbench domain must be untimed, any of the aforementioned explicit timing control statements left in that code must be removed, and if necessary re-implemented by synchronization with the timed HDL domain through the task-based BFM communication interface described above.
Worked Example
The methodology pages contain a simple example. Another more comprehensive example illustrating the methodology can be found here.
|