You’re Either With Me Or You’re With: The UVM Register Package

Let me take you back a few years to my first job as an ASIC verification engineer. It was 2000 and things were a lot different. The notion of “architecting a testbench” didn’t really exist the way it does today. Design was cool and verification was where junior engineers started. Constrained random verification hadn’t hit the mainstream. There wasn’t much functional coverage to speak of. I think Specman and Vera were around but the user-base was relatively small. There was no Systemverilog and there was no UVM. Basically, we were back in the stone age of directed testing. Any knucklehead could do it. Thankfully, I was perfectly qualified.

To test a processor interface back in the stone age we’d first need to build a behavioural model. The processor model was usually quite basic. On one side we’d have pins; on the other side we’d have a user interface with 2 methods: read and write. If I remember right, every write and read method I ever saw back in the stone age had an address argument and data argument. If we were well organized, we’d have a long list of macros to define address space so we could access registers and fields by name. Maybe we’d have some means of injecting protocol errors on the bus or an additional option for burst size but that’s about it.

Once we were done writing our processor model, we connected it to our DUT in a testbench module and start writing tests (in the stone age there was no class-based environment). A couple weeks would go by and we’d see that the start of the first few tests looked pretty similar. It became obvious that consolidating that long list of writes at the beginning (i.e. your initialization sequence) was a good thing to do to keep things tidy so we pulled them out and added an initialization task to the testbench. Otherwise, in each test we’d peek and poke through various parts of our DUT using the write and read functions on our processor model. Practically speaking, there was only a short list of registers we’d interact with frequently. The functionality of the others would probably be verified in their own directed tests (obviously we had to understand what each register did so we could manually predict the outcome).

The last thing we always used to do was the front-to-back accessibility tests. We’d go through the entire address space, writing and reading back every register to make sure they were all connected properly. Sometimes the design would change, which meant our tests would need to change, too (or better, just the register/field macros would change). That was annoying but it happened.

Simple testbench; simple processor model with a simple user interface; tests that junior engineers could write and others could understand. Not elegant but adequate.

A lot has changed in the last 14 years.

I just counted 26 different classes in the UVM register package. Add to that the sequence related classes and you’re at 37. That’s what we use now to write and read registers! It’s elegant for sure. It’s highly portable and it’s designed to serve a universal purpose. But add up the code in the src/reg directory and you get 21551 lines (I just double checked that number to make sure I had it right). And that’s just the base classes. After defining the registers in your DUT, obviously you end up with far more.

Lots of features; lots of code. On it’s own that’s not necessarily a bad thing. But the part that does irk me, that I do think is a bad thing, is that the junior engineer that used to build the processor model and lead the testing is out of a job. They’ve been replaced by a senior engineer – sometimes many senior engineers – who construct, automate, connect, integrate and/or customize the driver, sequencer(s) or virtual sequencer(s), register maps, various transactors and agents. Then there’s the sequences – usually a base sequence with a list of derived sequences – that’ll be made available to other agents and tests.

None of the above even remotely resembles the stone age write/read API. Worst case, it’s a make work project that sucks in productive people (it’s not the norm but it does happen). I’m hoping there are other hardware developers out there that see that as a problem.

If you see it as a problem, do yourself a favour… the next time you’re getting started with the UVM register package, go to a quiet room and think about the value you’re about to add. I mean really think about it because you’re about to invest a serious chunk of your time.

Take yourself back to the stone age when we didn’t need 26 different classes to write and read a register (if you’re too young to remember the stone age, ask old-timer to tell you the stories). We didn’t need to ensure everything we did was universally portable. We didn’t need to randomly juggle the order in which we accessed registers in our accessibility tests. There wasn’t an automatic need to consolidate an accurate image of the memory space and make it R/W accessible to every component in the testbench via all possible bus masters. We didn’t need to hide and randomize the selection of a bus master. We didn’t need functional coverage for every possible situation in every possible register (to account for the fact that we don’t know what our random tests are actually doing). We didn’t need an afternoon and a whiteboard to explain to designers how to access a register in their code. We didn’t need a cookbook or a training class. We could look at a test and understand what’s happening.

Finally, and most importantly, it didn’t take senior engineers to “architect a testbench” that enables all of the stuff that didn’t used to be necessary. We could all do what needed to be done, even the knuckleheaded 2000 version of me.

So? What say you? Are you with me or are you with the UVM register package?


10 thoughts on “You’re Either With Me Or You’re With: The UVM Register Package

  1. Interesting article. I am a Junior Engineer. And for me personally I can say that I have been developing register maps (including automation of generating the SV UVM RegModel code), UVCs (including monitors, sequencers, drivers) and Verification Environments. The UVCs I have developed have been successfully reused on several projects.

    I have worked at projects where UVM Register Package has been used and others where it has not been used. The issue is that register map changed throughout the developement several times and the UVM Register package definatelly is a huge help and time-saver whenever changes such as address change are done. The code is also easier to read.

    So I don’t think the situation is as bad. As a Junior Engineer I have been working on developing a lot of the things you mention only Senior Engineers do. 🙂

    1. ouch! less than a day and already someone counters with an experience fully and completely different from my own. UVM register package 1… neil 0.


      1. I think it’s always interesting to hear how things work in other companies and maybe learn a little bit how I can improve what I’m doing myself. Unfortunatelly I haven’t had a lot opportunities to get inside views from other places sofar.

        At the company where I work, a decision has been made not to buy a tool for generating the SV code, but developing our own tool for documenting the whole register map. I have been the one developing the whole project. The tool eventually has not been used only for generating the register model, but also other generated files such as Word/PDF register map description etc.

  2. I agree that uvm_reg seems far to complicated. But sorry, Neil. Our Junior engineer did our register testing with uvm_reg too. 🙂

    Actually, we paid for a tool that generated all the uvm_reg stuff and he and a senior design engineer (because the tool generated RTL for registers too) got it all working, so that’s not quite fair of me to say.

    The funny thing in my mind is that, since it is all generated code, we most certainly did not need all the generality and flexibility that uvm_reg is trying to provide. If the tool generated simple inflexible code and something changed we could just re-run the tool and generate new code.

    My biggest problem with the UVM is not so much that it tries to provide so many features, it’s that people seem to believe that they absolutely must use all those features. Fortunately on my team we mostly don’t fall into that trap. Mostly 🙂

    1. Ha! down 2 zip!

      that would have been a better point to make… it serves a purpose if you use the features you need and disregard the features you don’t need. if you’re trying to use all the features you end up with more time spent and no value to show.


    2. Hi Bryan,

      I pretty agree with you that UVM is only a method with many features, what we really need is depend on our spec and our plan.

      Can I ask a small question on the tool we are generating for UVM_REG, such a tool can generate all the code based on some format of files such as XML. I have used the code to integrate but never try to generate the code (missing this experience), I am curious that before generating codes, what kind of communication you need to do with your architect? How do you align with them the format of files? (for example, if nobody give you the xml file, how do you start?)

      1. When we started using the register generation tool (Semifore, actually) we had an existing design already, so it was a matter creating the register specification (csrspec with Semifore, but it could be xml or whatever your tool takes as input) based on the existing design and then running the register generation tool and then replacing the old hand-coded registers with the new generated registers. It was tricky to make that happen amidst all the other development that was going on at the time, but it feels like it was worth the effort. Now when new registers are added they go in the csrspec file and then new verilog, new c header files, new uvm_reg, and new documentation is all generated.

  3. Designs of today have 1,000’s to 100,000’s of registers. Without a generator, regardless of the underlying representation, your project is doomed. Perhaps uvm_reg is overly complicated in some ways, but it may just reflect the complexity of modern designs and the cost of reuse.

    Of course it would help if there wasn’t such a diversity in designs out there, but then we might not the interesting products we do. Yesterday was simpler, but we didn’t have Cray computers in our pockets either.

    I guess you can count me with uvm_reg. Let me know when you’re ready to join. Of course you don’t have to make it so black and white. We could just choose to work together to improve it.

  4. I agree with David here, we do need register packages for today’s 1000 to 100000 register designs but also for smaller ones.

    I was working on a project where they started out with OVM and they implemented their own register classes because back then there was no standard approach. Now we moved to UVM, but we didn’t change that register stuff (yet?). Think of how much code could be saved by using an already existing solution. If it has wide industry adoption it also makes it much easier for newbies in the project to jump in and use it.

    I’m not saying uvm_reg is perfect (I do find it a bit bloated in some parts and lacking in others , but it’s better then nothing (I for one would have preferred they take the Cadence package because it’s modeled after vr_ad).

Leave a Reply

Your email address will not be published. Required fields are marked *