Posts

The highs and lows of UVM

I just read this article Accellera DAC 2014 Breakfast—What Engineers Really Think About UVM) . They hit a few interesting points. I'd like to add another few points that I think were missed in this discussion. The highs UVM helps the developer create reusable components (though I have seen UVM components and sequences written so badly, that it would've been impossible to reuse them without bringing in the whole kitchen-sync). Already mentioned in the article is the adoption of the vendors (a kind mention to Synopsys , navigating UVM hyper linked and filtered test logs is a big time save [I suppose other vendors have them too, just writing from experience]). The lows Vendor issues The register model: we need better support from vendors for creating a nice and easily extensible register model (Synopsys: ralgen sucks). uvm_reg_adapter: VIP vendors please provide a uvm_reg_adapter for your agents, at least a standard one that can be somehow be built upon. Code vi

UVM register model coverage woes - part 2

So after I described my troubles with the UVM register model's coverage in my previous post , I revisited the issue in a slightly different context and discovered the current solution was rather lacking. Register block coverage In the previous example, coverage was taken for a value written via the register model. You access the data provided by the sample method, so you don't need any visibility into the register model you're covering. But what happens if you want to cover a bunch of registers, say you want to sample the values of various registers by calling the sample_values method after configuring them. In this case you need to be able to access the register classes which you won't be able to do as you're in a wrapper class, and not in the register block class. Two possible solutions Define the sample function for the various covergroups to include values of multiple registers. In the sample_values function call the sample function with the required value

The crooked ways of UVM's register model's coverage methods

"Welcome to the world of Coverage" I have been dabbling now for a couple of weeks with coverage. Working my way through the SV LRM, looking at some examples and running a few simple cases. My first case was some protocol coverage. We wanted to verify certain types of traffic are getting through the design. I extended a uvm_subscriber for that purpose, added a covergroup as part of the class, instantiated the covergroup in the new function of the class and called the sample function in the write function of the subscriber: class my_coverage_collector extends uvm_subscriber #(trans_type);      ...      covergroup my_covergroup;           ....      endgroup      function new ( string name = "my_coverage_collector",                   uvm_component parent = null);            super.new (name, parent) ;          my_covergroup = new;      endfunction      function write(trans_type t);          my_covergroup.sample() ;      endfunction endclass Si

uvm_config_db vs uvm_resource_db, where they come from and what are they good for

The origins According to a story I was told, the origin of the uvm_resource_db stems from the fact that certain simulators (if I remember correctly Mentor's Modelsim/Questa), were unable to cope with the dot-notation. Eg. You could not write m_object.m_field = 1 , instead you'd have to put the field value into uvm_resource_db and pull the value at the "other" side. Uvm_config_db was created so as to simplify issues with namespace collisions. Set and get functions for the config_db accept as a first argument a uvm_component. The component is only used so as to get a full hierarchical name for the object's name, thereby protecting the namespace from being polluted. Eg., an environment that would need to set a field within a agent/scoreboard residing within that environment would pass the set function this as its first argument and the agent/scoreboard's instance name as it's second argument. The component (agent/scoreboard) would be pullin

My issues with uvm_reg's predict method

A couple of weeks ago, I created a status register callback class. The purpose of it was to create a built-in scoreboard allowing me to predict the value of a status register based on the known status signal's input. I'll maybe post the code in a sometime in the future. I've used this code to pass UVM's bit-bash test, as it allows for the prediction of status registers with a "unknown" value. This week, I tried using this callback class in my home brew sequence. This was the first-time I called uvm_reg 's predict method directly from within my sequence. I discovered during this experiment a bug and a bad API call. The bug is the fact that by default the field's callback functions won't be called, as when predicting with kind set to UVM_PREDICT_DIRECT , UVM does not call the post_predict callbacks. So be careful to set kind to UVM_PREDICT_READ or UVM_PREDICT_WRITE . My issue with the API call is the fact that a value must

Always assert your randomizations

Today I was bitten twice by the same issue: randomization .   When you randomize something you should always assert the randomization. This will allow you to find the source of the problem much quicker. I lament the fact that UVM sequence macros do not assert the randomization by default. Instead they issue a warning with id RNDZFLD .   By the way, in case the randomization failed, you can rerun the simulation with the -solvefaildebug switch if running Modelsim/Questa. This will give you an idea why the solver was unable to satisfy your constraints.

Don't use null as a sequencer argument to uvm_reg_sequence

Back when I started using UVM, I had no use for a register model for the specific unit I was testing. As such, sequences were written which needed a sequencer which would hand the items in the sequence to the driver. Over time, we moved to use the register model and its uvm_reg_sequence. At first I would pass the sequencer of the agent responsible for sending the transaction to the sequence. But then I discovered this to be error prone: sometimes the sequencer would not exist because the agent had been declared to be UVM_PASSIVE, in another case I needed to dig deep to find the sequencer to be used. Looking at the code I also discovered that while sending a protocol sequence to a specific sequencer made a lot of sense, a register model (or more specifically a register map) would already be bound by the environment's maintainer to the correct sequencer causing the reg sequence to disregard the sequencer argument given to it and accessing the register according to the map's def