Posts

Showing posts from 2013

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