Overview.

Special registers are registers that have different characteristics than those provided by default in the UVM register base class.

A general technique to implement special functionality is to extend the base class, and modify the virtual functions that affect behavior.

An example of a special register might be a register that clears to zero after being read 3 times.  Out-of-the-box, the base class library supports a clear-on-read register, but it doesn’t have a built in “counter” to keep track of number of times read.

In this case, the functionality can be supported easily by extending the built-in uvm_register base class, and overriding the virtual function ‘read_without_notify()’ to achieve the desired behavior.

Included below is the complete implementation for such a special register.  Using this technique, it is possible to build any number of special base classes that each implement special functionality.  This particular register implementation is not that interesting, expect for people who erase their data after three reads.

class my_c3_register #(type T = int)
    extends uvm_register #(T);
  int counter;

  function new(string name, uvm_component p,
      bit32_t resetVal = 0);
    super.new(name, p, resetVal);
    counter = 0;
  endfunction

   virtual function T read_without_notify(T local_mask = '1);
     T val = super.read_without_notify(local_mask);
     if (counter++ >= 3) begin
       poke(0);
       val = super.read_without_notify(local_mask);
       counter = 0;
     end
     return val;
   endfunction

   virtual function void reset();
     super.reset();
     counter = 0;
   endfunction
 endclass