C++ ... Really?
As SystemVerilog has matured and its usage has become widespread it seemed that the use of C++ in testbenches had all but disappeared. But it is making a resurgence and will likely keeps its place within the pantheon of verification languages for the foreseeable future. The promise of SystemVerilog, with its classes, dynamic memory allocation, and other "testbench" features is that you will only need one language for all your design and verification needs. This promise has not been fully met.
Before the advent of SystemVerilog, C and C++ were used widely to build testbenches. The PLI facility in Verilog provided an interface for accessing objects like registers, nets, and modules within a Verilog design. C/C++ along with PLI seemed like the perfect environment for building testbenches. It was -- for a while until people discovered a couple of things. One was that PLI is slow. Providing access to internal objects meant simulator vendors had to disable certain optimizations. The mechanical details of allowing users to safely access the internals of a simulator engine at run-time proved to be, well, slow. Another thing is that C++ is C++. It's not the easiest language to master. You have to deal with lots of low-level details that aren't particularly fun, nor are they germane to the problem of verifying a design. Things like constructors and destructors, memory management, and pointers vs. references. You need to make sure the copy constructor and operator=() functions are written correctly, and so on. Ick.
The biggest problem with using C++ to build testbenches is that the language does not natively know anything about hardware or about time. There is no such thing as a port or net, and there is no such thing as a delay. You have to call back to the simulator (through PLI) to pretend that you are manipulating hardware objects and time. It was not convenient. There were some attempts to build layers that provide the necessary abstractions. They did not help the performance issue, and, in the end, they weren't Verilog. The abstraction layer still looked like C++ and not Verilog.
SystemVerilog was just the thing that the industry needed. It had all the software-ish things that people liked about C++ AND it had built in abstractions for hardware objects. You can access nets and registers, manipulate time, as well as dynamically allocate memory and write recursive functions. In addition it avoided the things that people did not like about C++. Yes, there are constructors, but no destructors. No need to worry about copy constructors and overloaded functions, and all the hocus pocus that can drive you mad when writing C++. Further, the performance is way better than PLI code.
All was great until the world of SoC design began to overtake the world of verification. SoCs run on processors, lots of them, and processors run on C code. No one writes SystemVerilog code to run on an embedded processor. That would be weird. Hardware access layers, low level drivers, executives and operating systems, and applications that run on SoCs are all written in C/C++. So, if you want to write a test that will run on an SoC, it has to be written in C/C++. If you want your test to use some of pieces of your software stack you need to use C/C++. If you want your test to work in the bring-up lab (on silicon) as well as in your verification environment, you need C/C++.
As a result, SoC manufacturers began to quietly build great libraries of C/C++ code to test their designs. Over the years, this body of C++ code has become quite substantial. It includes specialized routines that exercise the design in application-specific ways as well as actual application code and other parts of the software stack. It's not code that can be easily replaced -- it's part of each company's internal IP.
C/C++ still does not have any hardware elements, and it cannot manipulate time. This is just fine with the software teams. They are not worried about the hardware per se. The tests they write are about the entire system. The term "system-level" means a complete system that includes hardware and software. Those writing system-level tests can safely assume that the units have been thoroughly verified. The problem is to demonstrate that the hardware functions correctly under control of the software stack. The software view is the system view.
The C++ community is still vibrant and and the language is still evolving as evidenced by C++11, C++14, and now C++17. It's a very ubiquitous language with chameleon-like characteristics. It can be used to write very low-level hardware-aware code such as HALs and drivers. The same language can also be used to write high-level applications utilizing the latest in object-oriented, pattern-driven methodologies. The TIOBE index, which tracks the popularity of programming languages worldwide, still shows C and C++ as the number 2 and 3 most popular languages (Java is number 1). Verilog is lumped into the group of 51st to 100th most popular languages.
High performance embedded systems are driven by C/C++ code. As the size and complexity of those systems grow, more C/C++ code will be written to run them. With some of the system interfaces going through the software stack there's no doubt that code will be drawn into verification environments. Verification engineers would do well to make sure their skill set includes C/C++ as well as Verilog and SystemVerilog. (A bit of Python, too, couldn't hurt.)
C/C++ code is here to stay in verification environments. Embrace the future.