Tuesday, February 7, 2017

SystemVerilog and Python

Design patterns in programming are when engineers find themselves writing the same code over and over to solve the same problems. Design patterns for statically typed object oriented languages (C++ and Java) were cataloged and enshrined in the famous book, "Design Patterns: Elements of Reusable Object-Oriented Software" by Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm. The authors are lovingly called, The Gang of Four, or the GOF and the book is often referred to as the GOF book.

The subset of SystemVerilog used in writing testbenches is a statically typed object oriented language (it's most similar to Java). As people started using SystemVerilog to write testbenches, frameworks for writing testbenches quickly became popular. These frameworks all provide code that implements design patterns from the GOF book. The various frameworks were similar because they were all essentially implementing the same design patterns. Eventually the various frameworks all coalesced into one, the humbly named, Universal Verification Methodology, or UVM.

Below is a table that matches up GOF design patterns with their UVM implementation. This was adapted from this presentation:

GOF Pattern Name UVM name 
Factory Method, Abstract Factory uvm_factory, inheriting from uvm base classes 
Singleton UVM Pool, UVM Global report server, etc. 
Composite UVM Component Hierarchy, UVM Sequence Hierarchy 
Facade TLM Ports, UVM scoreboards 
Adapter UVM Reg Adapter 
Bridge UVM sequencer, UVM driver 
Observer UVM Subscriber, UVM Monitor, UVM Coverage 
Template Method UVM Transaction (do_copy, do_compare), UVM Phase 
Command UVM Sequence Item 
Strategy UVM Sequence, UVM Driver 
Mediator UVM Virtual Sequencer 

If we switched from SystemVerilog to Python for writing our testbenches, would we need to re-implement each of those parts of the UVM? Python is not a statically typed object oriented language like Java and SystemVerilog. It is a dynamically typed language. Prominent and well respected computer scientist Peter Norvig explored this topic for us already. He did this when Python was still a very young language, so he examined other dynamic languages instead (Dylan and Lisp) and he concluded that of the 23 design patterns from the GOF book, 16 of them are either invisible or greatly simplified due to the nature of dynamic languages and their built-in features. As an example to explain how this could be, he points out that a defining a function and calling it used to be design patterns. Higher-level languages came along and made the pattern of defining and calling a function a part of the language.

This is essentially what has happened with dynamic languages. Many design patterns from GOF are now simply part of the language. According to Dr. Norvig, the patterns that dynamic languages obsolete are:

  • Abstract-Factory
  • Flyweight
  • Factory-Method
  • State
  • Proxy
  • Chain-Of-Responsibility
  • Command
  • Strategy
  • Template-Method
  • Visitor
  • Interpreter
  • Iterator
  • Mediator
  • Observer
  • Builder
  • Facade

That reduces the above table to:

GOF Pattern Name UVM name 
Singleton UVM Pool, UVM Global report server, etc. 
Composite UVM Component Hierarchy, UVM Sequence Hierarchy 
Adapter UVM Reg Adapter 
Bridge UVM sequencer, UVM driver 

Trusting that, if we were to write a pure Python testbench we can see that we would still likely implement a few design patterns. Thinking about this, it makes sense that we'd still probably have classes dedicated to transforming high-level sequence items to pin wiggles, just like the sequencer and driver work together to do in the UVM. It also makes sense that we'd have a class hierarchy to organize and relate components (such as the sequencer and driver equivalents) and sequences (high-level stimulus generation). Thing like that.

The more striking thing is the amount of code we would not need.

5 comments:

Gordon McGregor said...

I have a repository somewhere called PyUVM with a lot of the UVM classes re-implemented in cocotb or with their rough equivalents, so that testbenches could be written using a similar underlying methodology (or communicate between the python and SV layers)

I'd agree with most of your analysis here in terms of what patterns are needed to implement various pieces of the UVM library.

I do maybe disagree with the idea that your table matches patterns to 'their UVM implementation'. I'd rather say that the implementation of many of the pieces of the UVM library uses various patterns. That may be a subtle distinction, but things like the Global Report Server doesn't implement a singleton, but it does use the singleton pattern to create one instance of the report server.

Gordon McGregor said...

For good or for ill, the repo is still there.

https://bitbucket.org/GordonMcGregor/pluvm

Bryan said...

"I do maybe disagree with the idea that your table matches patterns to 'their UVM implementation'. I'd rather say that the implementation of many of the pieces of the UVM library uses various patterns. That may be a subtle distinction..."

It is indeed subtle, but though provoking. If someone were to spend more time on this they could look at each UVM thing and see if it exist solely to implement a design pattern in ancillary support of solving the the meat of The Verification Problem (e.g., uvm_factory), if it's providing core functionality and would use that design pattern no matter which language you use (e.g., global report server), or if it's core functionality that's making use of a design pattern and probably could be simplified or done a different way (e.g., uvm_sequence/strategy pattern could just be a function in a dynamic language).

I'll definitely take a look at your code, thanks for sharing that!

Gordon McGregor said...

I will say that if you look at the code, you'll see there isn't much there. Which is rather the point you were making here too. It was certainly very early development, but as I sketched out the objects I found there wasn't a whole lot to implement in them.

Anonymous said...

I do frontend work and lab silicon eval. All the lab work is done in Python. I really wish that I could just standardize with Python for testbench and lab. That way lab routines are just a subset of the testbench. I am thinking that the only way for that to happen is for Python to be used as the HDL.
I remember when people wanted to move to systemc, but it did not have the lab infrastructure that Python does.
Just a thought.