Over the past few years I've been building verification environments in Python, hooked up to SystemVerilog and Verilog simulators. The glue is PyHVL. But PyHVL is just the glue. It does open up the possibility of dynamic languages and scripting to talk to your test bench, but it isn't enough to implement a complete verification environment, quickly.
To that end, I've started building analogues for most of the UVM classes, in Python/ PyHVL. Monitors, drivers, checkers, interfaces, scoreboards, all the standard sorts of pieces that you'd expect from a modern verification environment. With no compiling between iterations, and a command-line REPL to drop to for debug and interactive exploration. All backed with the batteries-included philosophy of Python. The sweet spot for this is probably somewhere within a fully fleshed out SystemVerilog testbench, leveraging the best features of SV (RTL/design, randomization with constraints, coverage, assertions) with the best features of Python for the higher level pieces of the testbench. At the same time, there is the potential to write the entire testbench in Python and the whole design in Verilog and use a free simulator such as Icarus or CVer. Python brings a variety of useful features for testbench development; dynamic language, rapid development, rich set of libraries, fast iteration and a high level programming abstraction.
I've been able to write models of processors that actually execute instructions and check the RTL, where the initial development time for a working CPU model was about 4 hours. There is effectively no recompile time cost - just re-run and the Python verification environment is re-interpreted as the simulation starts up.
The main advantage of using Python for a testbench is writing less code. Less code means fewer bugs. The higher level language features of Python let you write more efficient code. As a quick example, here is the entire class definition for a PyHVL/ UVM interface, ready to hook up to RTL and monitor/drive signals in a DUT.
from pluvm.uvm_package import * HOST_BUS_SIGNALS=('reset', 'clock', 'cycle_count', 'host_rdata', 'host_ack', 'host_err', 'host_address', 'host_valid', 'host_wdata', 'host_strobe', 'host_rwb') class host_interface(uvm_interface): def __init__(self, name, hierarchy): uvm_interface.__init__(self, name, hierarchy) for signal in HOST_BUS_SIGNALS: self.add_signal(signal)
These classes can of course leverage the standard pyunit test frameworks and have unit tests in every class.
There are comments.