Quantcast
Channel: UVM Methodology and BCL Forum RSS Feed
Viewing all 283 articles
Browse latest View live

How to Use Virtual Sequencers to Control Both Non-virtual Sub Sequencers and Virtual Sub Sequencers

$
0
0

Hello Everyone,

 

Good day.

I am creating a testbench that has a structure shown below and am encountering errors perhaps due to the multi-layered virtual sequencer controlling both non-virtual sub sequencers and a virtual sub sequencer. Config's not shown.

<start of diagram>

                       .------------------------------------------------------.

                       | my_test                                              |

                       | .--------------------------------------------------. |

                       | | sequences                                        | |

                       | '--------------------------------------------------' |

                       | .--------------------------------------------------. |

                       | | my_env                                           | |

                       | '--------------------------------------------------' |

                       '/----------------------------------------------------\'

                       /                                                      \

                      /                                                        \

                     /                                                          \

                    /                                                            \

                   /                                                              \

                  /                                                                \

                 /                                                                  \

                /                                                                    \

               /                                                                      \

              /                                                                        \

             /                                                                          \

            /                                                                            \

           /                                                                              \

          /                                                                                \

         /                                                                                  \

        /                                                                                    \

       /                                                                                      \

      /                                                                                        \

     /                                                                                          \

    /                                                                                            \

   /                                                                                              \

  /                                                                                                \

 /                                                                                                  \

.----------------------------------------------------------------------------------------------------.

| my_env                                                                                             |

|                                     .------------------------.                                     |

|                                     | my_virtual_sequencer   |                                     |

|                                     '------------------------'                                     |

| .-----------------------------------. .----------------------------. .---------------------------. |

| | sub_virtual_agent                 | | sub_agent_a                | | sub_agent_b               | |

| | .-------------------------------. | | .------------------------. | | .-----------------------. | |

| | | sub_virtual_sequencer         | | | | sub_sequencer_a        | | | | sub_sequencer_b       | | |

| | '-------------------------------' | | '------------------------' | | '-----------------------' | |

| |       .-------------------------. | | .------------------------. | | .-----------------------. | |

| |       | sub_agent_3             | | | | driver_a               | | | | driver_b              | | |

| |     .-------------------------. | | | '------------------------' | | '-----------------------' | |

| |     | sub_agent_2             | | | | .------------------------. | | .-----------------------. | |

| | .---------------------------. | | | | | monitor_a              | | | | monitor_b             | | |

| | | sub_agent_1               | | | | | '------------------------' | | '-----------------------' | |

| | | .-----------------------. | | | | '----------------------------' '---------------------------' |

| | | | sub_sequencer_1       | | | | |                                                              |

| | | '-----------------------' | | | |                                                              |

| | | .-----------------------. | | | |                                                              |

| | | | driver_1              | | | | |                                                              |

| | | '-----------------------' | | | |                                                              |

| | | .-----------------------. | | | |                                                              |

| | | | monitor_1             | | |-' |                                                              |

| | | '-----------------------' |-'   |                                                              |

| | '---------------------------'     |                                                              |

| '-----------------------------------'                                                              |

'----------------------------------------------------------------------------------------------------'

<end of diagram>

 

1) my_base_sequence (from w/c my_sequence_1 is extend)

<start snip>

class my_base_sequence extends uvm_sequence #(my_sequence_item);

  `uvm_object_utils(my_base_sequence)

  `uvm_declare_p_sequencer(sub_sequencer_1)

  function new (string name ="my_base_sequence");

    super.new(name);

  endfunction

  virtual task pre_start();

    if(get_parent_sequence() == null && starting_phase != null)

      starting_phase.raise_objection(get_sequencer());

    else

      `uvm_error(get_type_name(), "starting_phase is null")

  endtask

  virtual task post_start();

    if(get_parent_sequence() == null && starting_phase != null)

      starting_phase.drop_objection(get_sequencer());

  endtask

endclass

<end snip>

 

2) my_virtual_sequence

<start snip>

class my_virtual_sequence extends uvm_sequence;

  my_sequence_1 i_my_sequence_1;

  `uvm_object_utils(my_virtual_sequence)

  `uvm_declare_p_sequencer(my_virtual_sequencer)

  virtual task body();

    `uvm_do_on(i_my_sequence_1, p_sequencer.i_sub_virtual_sequencer.i_sub_sequencer_1);

  endtask

endclass

<end snip>

 

3) my_virtual_sequencer

<start snip>

class my_virtual_sequencer extends uvm_sequencer;

  sub_virtual_sequencer i_sub_virtual_sequencer;

  sub_sequencer_a       i_sub_sequencer_a;

  sub_sequencer_b       i_sub_sequencer_b;

  `uvm_component_utils(my_virtual_sequencer)

  function new (string name = "my_virtual_sequencer", uvm_component parent = null);

    super.new(name, parent);

  endfunction

  function void build_phase(uvm_phase phase);

    super.build_phase(phase);

    i_sub_virtual_sequencer = sub_virtual_sequencer::type_id::create("i_sub_virtual_sequencer",this);

    i_sub_sequencer_a       = sub_sequencer_a::type_id::create("i_sub_sequencer_a",this);

    i_sub_sequencer_b       = sub_sequencer_b::type_id::create("i_sub_sequencer_b",this);

  endfunction

endclass

<end snip>

 

4) my_env

<start snip>

class my_env extends uvm_env;

  my_virtual_sequencer i_my_virtual_sequencer;

  sub_virtual_agent    i_sub_virtual_agent;

  sub_agent_a          i_sub_agent_a;

  sub_agent_b          i_sub_agent_b;

  `uvm_component_utils(my_env);

  extern function new (string name = "my_env", uvm_component parent = null);

  extern function void build_phase (uvm_phase phase);

  extern function void connect_phase (uvm_phase phase);

endclass

function my_env::new(string name = "my_env",uvm_component parent = null);

  super.new(name, parent);

endfunction

function void my_env::build_phase(uvm_phase phase);

  super.build_phase(phase);

  i_sub_virtual_agent = sub_virtual_agent::type_id::create("i_sub_virtual_agent",this);

  uvm_config_db #(uvm_object_wrapper)::set(this, "i_sub_virtual_agent.i_sub_virtual_sequencer.i_sub_sequencer_1.main_phase","default_sequence",null);

  uvm_config_db #(uvm_object_wrapper)::set(this, "i_sub_virtual_agent.i_sub_virtual_sequencer.i_sub_sequencer_2.main_phase","default_sequence",null);

  uvm_config_db #(uvm_object_wrapper)::set(this, "i_sub_agent_a.i_sub_sequencer_a.main_phase", "default_sequence",null);

 

  uvm_config_db #(uvm_object_wrapper)::set(this, "i_sub_agent_b.i_sub_sequencer_b.main_phase", "default_sequence",null);

endfunction

function void my_env::connect_phase(uvm_phase phase);

  super.connect_phase(phase);

  i_my_virtual_sequencer.i_sub_virtual_sequencer.i_sub_sequencer_1 = i_sub_virtual_agent.i_sub_virtual_sequencer.i_sub_sequencer_1;

  i_my_virtual_sequencer.i_sub_virtual_sequencer.i_sub_sequencer_2 = i_sub_virtual_agent.i_sub_virtual_sequencer.i_sub_sequencer_2;

  i_my_virtual_sequencer.i_sub_virtual_sequencer.i_sub_sequencer_3 = i_sub_virtual_agent.i_sub_virtual_sequencer.i_sub_sequencer_3;

  i_my_virtual_sequencer.i_sub_sequencer_a = i_sub_agent_a.i_sub_sequencer_a;

  i_my_virtual_sequencer.i_sub_sequencer_b = i_sub_agent_a.i_sub_sequencer_b;

endfunction

<end snip>

 

5) my_test

<start snip>

class my_test extends uvm_test;

  my_env i_my_env;

  `uvm_component_utils(my_test)

  extern function new (string name = "my_test",uvm_component parent = null);

  extern function void build_phase (uvm_phase phase);

endclass

function my_test::new(string name = "my_test", uvm_component parent = null);

  super.new(name, parent);

endfunction

function void my_test::build_phase(uvm_phase phase);

  super.build_phase(phase);

  i_my_env = my_env::type_id::create("i_my_env",this);

  uvm_config_db #(uvm_object_wrapper)::set(this, "i_my_env,i_my_virtual_sequencer.main_phase","default_sequence",my_virtual_sequence::type_id::get());

endfunction

<end snip>

 

The result of this test run is as follows:

<start snip>

UVM_ERROR /some_path/my_sequence_lib.sv(693) @400000 : uvm_test_top.i_my_env.i_sub_virtual_agent.i_sub_agent_1.i_sub_sequencer_1@@my_virtual_sequence.i_sub_sequence_1 [my_virtual_sequence] starting_phase is null

. . .

UVM_INFO /cad_tools_path/F-2011.12-SP1/etc/uvm/base/uvm_phase.svh(1233) @400000 : reporter [PH_READY_TO_END] Phase 'uvm.uvm_sched.main' (id=2956) PHASE READY TO END

<end snip>

 

And then it ended w/o running the sub_sequence_1.

The UVM_ERROR above shows that it was unable to get the raise.objection part to run.

Any help/inputs to this is much appreciated.

 

Thanks,

Martin


How to Control a Multi-layered Agent's Sub Sequencer Using a Top Level Virtual Sequencer

$
0
0

Hello Everyone,

I am trying to control a sub virtual sequencer's non-virtual sub sequencers using a top level virtual sequencer.
It looks like this diagram.

<start of diagram>

                       .------------------------------------------------------.
                       | my_test                                              
                       | .--------------------------------------------------. |
                       | | sequences                                        | |
                       | '--------------------------------------------------' |
                       | .--------------------------------------------------. |
                       | | my_env                                           | |
                       | '--------------------------------------------------' |
                       '/----------------------------------------------------\'
                       /                                                      \
                      /                                                        \
                     /                                                          \
                    /                                                            \
                   /                                                              \
                  /                                                                \
                 /                                                                  \
                /                                                                    \
               /                                                                      \
              /                                                                        \
             /                                                                          \
            /                                                                            \
           /                                                                              \
          /                                                                                \
         /                                                                                  \
        /                                                                                    \
       /                                                                                      \
      /                                                                                        \
     /                                                                                          \
    /                                                                                            \
   /                                                                                              \
  /                                                                                                \
 /                                                                                                  \
.----------------------------------------------------------------------------------------------------.
| my_env                                                                                             |
|                                     .------------------------.                                     |
|                                     | my_virtual_sequencer   |                                     |
|                                     '------------------------'                                     |
| .-----------------------------------. .----------------------------. .---------------------------. |
| | sub_virtual_agent                 | | sub_agent_a                | | sub_agent_b               | |
| | .-------------------------------. | | .------------------------. | | .-----------------------. | |
| | | sub_virtual_sequencer         | | | | sub_sequencer_a        | | | | sub_sequencer_b       | | |
| | '-------------------------------' | | '------------------------' | | '-----------------------' | |
| |       .-------------------------. | | .------------------------. | | .-----------------------. | |
| |       | sub_agent_3             | | | | driver_a               | | | | driver_b              | | |
| |     .-------------------------. | | | '------------------------' | | '-----------------------' | |
| |     | sub_agent_2             | | | | .------------------------. | | .-----------------------. | |
| | .---------------------------. | | | | | monitor_a              | | | | monitor_b             | | |
| | | sub_agent_1               | | | | | '------------------------' | | '-----------------------' | |
| | | .-----------------------. | | | | '----------------------------' '---------------------------' |
| | | | sub_sequencer_1       | | | | |                                                              |
| | | '-----------------------' | | | |                                                              |
| | | .-----------------------. | | | |                                                              |
| | | | driver_1              | | | | |                                                              |
| | | '-----------------------' | | | |                                                              |
| | | .-----------------------. | | | |                                                              |
| | | | monitor_1             | | |-' |                                                              |
| | | '-----------------------' |-'   |                                                              |
| | '---------------------------'     |                                                              |
| '-----------------------------------'                                                              |
'----------------------------------------------------------------------------------------------------'

<end of diagram>

I am trying to apply section 4.8 Virtual Sequences of uvm users guide.
But I think I am missing on something.

I have a top level virtual sequence that has the top level virtual sequencer as its p_sequencer. I have this in the macro:

`uvm_declare_p_sequencer(my_virtual_sequencer)

And then I have this in the task body() to access the sub sequencer of the sub virtual sequencer:

`uvm_do_on(sub_sequence_1, p_sequencer.i_sub_virtual_sequencer.i_sub_sequencer_1);

sub_sequence_1 is a physical sequence.
Is this correct under the UVM standard?
If not, how do I properly control i_sub_sequencer_1?

This is how I access it in the test build_phase:

uvm_config_db #(uvm_object_wrapper)::set(this, "i_my_env,i_my_virtual_sequencer.main_phase","default_sequence",my_virtual_sequence::type_id::get());

Any help/inputs to this is much appreciated.

Thanks,
Martin

set_auto_predict()

$
0
0

Observation:

In  uvm_reg::write() set(value) is called immediatly while

uvm_reg::do_predict() is called at the end of the task.

In a case where auto_predict() set and an analysis port sends collected

transactions from the bus monitor to the reference model,

the analysis port write method may return before uvm_reg::do_predict() is called .

This will cause uvm_reg::get() to return the updated value but uvm_reg::get_mirrored_value() to return

the old value.

Proper placement of raise_objection in a multi-layered testbench with a virtual sequencer controlling sub sequencers

$
0
0

Hi All,

 

I have a question regarding the proper placement of the following code for raising an objection in a multi-layered testbench (i.e. virtual sequencer -> virtual sub sequencer -> sub sequencer):
<start snip>
virtual task pre_start();
  if(starting_phase != null)
    starting_phase.raise_objection(get_sequencer());
endtask

<end snip>

I have tested the physical sequences and they work when no virtual sequences are involved.
With that isolated, I introduced the 2 virtual sequences and since the new default_sequence is the top virtual sequence, I placed a raise_objection there.
Here is a summary of my trial runs:
1) Pure physical sequence as default_sequence - raise_objection at physical sequence (works);
2) Top virtual sequnce as default_sequence - raise_objection added to virtual sequence's pre_start (does not work);

What happens to 2) is the top virtual sequence does not end but the sub sequences do not run either.
Please shed some light on why this is happening and possible ways to fix this.

Thanks,
Martin

 

controling severity of uvm_comparer

$
0
0

I have this code in a sb :

 

sb_comparer.sev = UVM_ERROR
if(!expected_item.compare(received_item, sb_comparer)

but even so all the messages are printed:

UVM_INFO @ 8250000: reporter [MISCMP] Miscompare for tx2rx_sb_

I tried to check in uvm_comparer.svh :

function void print_msg (string msg);
    result++;
    if(result <= show_max) begin
       msg = {"Miscompare for ", uvm_object::__m_uvm_status_container.scope.get(), ": ", msg};
       uvm_report_info("MISCMP", msg, UVM_LOW);
    end
    miscompares = { miscompares, uvm_object::__m_uvm_status_container.scope.get(), ": ", msg, "\n" };
  endfunction

I cannot find were uvm_comparer::sev is  taken into account.

What am I missing ? (or is this a BUG in UVM)

`uvm_info_context - why use it?

$
0
0

In addition to the `uvm_info / `uvm_fatal / uvm_error, etc. macros, there are "context" versions: `uvm_info_context / `uvm_fatal_context, etc. The documentation is not exceptionally useful for the latter.

 

Why would one use the "context" versions of the macros?

 

Regards - Cliff Cummings

strange behavior in reg_driver in shipped UVM examples

$
0
0

Hi all,

 

I experiencing some strange things in the reg_driver which is shipped as part of the UVM 1.1d release.

 

Below the code snippet taken from the examples/simple/registers/common/reg_agent.sv:

class reg_driver #(type DO=int) extends uvm_component;
   ...
   task run_phase(uvm_phase phase);
      reg_monitor mon;
      $cast(mon, m_parent.get_child("mon"));

      forever begin
         reg_rw rw;
         seqr_port.peek(rw); // aka 'get_next_rw'
         DO::rw(rw);
         mon.ap.write(rw);
         seqr_port.get(rw); // aka 'item_done'
      end
   endtask
   
endclass 

In here, the driver communicates via the sequencer using the peek/get method (in this example there is no explicit response give, so no put method) The call in between the peek and get is DO::rw, where DO is a parameter which points to the dut in these examples. In this dut, the value of transaction/sequence_item rw will be changed.

 

And now the interesting thing: When we peek a value first and after this we get the value, I would expect we get the *same* result. I basically assume the sequence item is stored in a tlm_fifo and we first peek the value without clearing it, and with the get it and will be flushed from the fifo (aka item_done). However, in these examples, the 'get' results in a different value as the initial peek!

It gets even more funny as this (unwanted?) updated value is also returned back to the sequencer, which will call the bus2reg method to process the (unwanted?) updated value.

 

Instead I would expect the usage of a put or put_response method to report back any updated value. But when updating the reg_driver to provide a response (and adding the provides_responses = 1 to the adapter component) some examples, like the register aliasing example, seems to break.

 

I would appreciate any input to clarify if this changed transaction item between the peek and get is really intendend, and if not, whether the exampels can be updated accordingly.

 

Thanks,
Martin

 

Parametrized UVM Verification Environment

$
0
0

Hi all

 

I'm trying to build a generlc verification environment for specific modules of mine, that essentially only differ (besides their actual implementation) by the number of inputs/outputs of a certain interface standard and the data_size of each of these interfaces.

 

This leads to the point, that I like to have an environment, where I can set the number of interfaces and for each of these interfaces the data_size.

 

Unfortunately this simple setup of non-dynamic pre-compile settings is getting me in a lot of trouble.

 

(1) Sequence_Item

 

class input_item #(int unsigned data_size) extends uvm_sequence_item;
    `uvm_object_param_utils(input_item)
    
    rand logic[data_size-1:0] data;

   .......


 

The first question that comes to mind writing this code is the following:

 

Is it possible to factory overwrite a param. class with another specilisation of that same class (e.g. define a driver with input_item<32> and then factory overwrite it with input_item<42>)?

Otherwise a item_base class would be necessary that than would be extended by this class.

 

 

(2) Analysis Ports

class env extends uvm_env;
 ....

    // need N = number of interfaces analysis ports between each monitor and scoreboard
    uvm_analysis_port #(input_item#(17)) ap_1;
    uvm_analysis_port #(input_item#(12)) ap_2;
    .....
    uvm_analysis_port #(input_item#(42)) ap_N;


....
    

 

Due to the different input_items all ports are of a different type. Therefore it is not possible to create an array of N=number_of_interfaces, which leads to this not being possible to implement. Furthermore the analysis_port/export classes cannot be overwritten through the means of the factory.

 

 

(3) Virtual Sequence

 

class top_vseq_base extends uvm_sequence #(uvm_sequence_item);
 
`uvm_object_utils(top_vseq_base)
 
      uvm_sequencer #(input_item#(17)) seq_1;
      uvm_sequencer #(input_item#(12)) seq_2;
      ...
      uvm_sequencer #(input_item#(42)) seq_N;

 

In the virtual sequence I essentially run into two problems:

 

1. The first one is the same problem as in (2) of not being able to create an array of different types or having a pre-processor for-loop 

2. The other one is the fact, that I'm not able to get access to the number N . Even if they were all of the same type and I would declare a dynamic array, there is no build_phase and no way to get informations through either the config_db or "p_sequencer.variable". I could put a member variable into the virtual sequencer, but I'm not sure if it is a good idea/possible to create a dynamic array in the body method.

 

 

General Solutions so far:

 

I only see two solutions here ...

 

1. Defining a gigantic input_item with data_size of 256/512 and then cut it everywhere. But unfortunately I will be in need of an array of completely different items in the next version of this environment anyhow. The reason for that is, that I would like to group a bunch of M different interfaces into one environment, all of them running a different item. Therefore the analysis_ports would all run a different item.

 

2. Just building a code generator, in which the user sets all parameters, creating the necessary environment for the given DUT.

 

 

If you have any input, I would be glad to hear it.

 

Thanks

 

Marcel


controlling test message severity from command line

$
0
0

what arguments  are passed to +uvm_set_severity 

in order to cancel all `uvm_info for all components ?

UVM Phase issue

$
0
0

Hi UVM Experts,

 

I am facing some issue with UVM phase. I have registered one sequence to pre_configure phase of one sequencer which is doing some chip configuration.

In my base test pre_configure phaseI am waiting for that configuration to get over usng hierarchy of RTL path signal. RTL takes some time after configuration gets over to toggle the indication of chip ready which i am waiting in base test pre_configure phase. I observe that sequence gets over but immediately test also gets finished even i raised the objection from base test pre_configure phase.

 

Would you please point me if it is exptected? I think till all raised objections are not lower simulation will not be over. and I want my test to wait once sequence is over and RTL toggles ready signal.

 

Thanks in advance for your time.

 

Thanks,

Akshay

 

Auto-generate doc script, UVM to HTML

$
0
0

Hi,

I have a question regarding Auto-generate doc script, UVM to HTML:

We're in a process of defining UVM coding guidelines in our group.

We would like to guide engineers to write code and comments in a way that a script can run to auto-generate HTML doc from comments (to document classes, functions, variables, macros, etc).

We've noticed that UVM class reference doc was auto-generated from comments in UVM library files.

does this script (that generate HTML) is part of UVM library ?

can we run it on our own code to generate HTML ? if yes, then how ?

Is it releated to $UVM_HOME/docs/html/javascript/ (main.js, searchdata.js) ?

What are the coding guidelines to support this script ?

 

it seems the script search for comments in such format:

// CLASS: uvm_sequencer #(REQ,RSP)

// Variable: seq_item_export

// Function: new

// Function: stop_sequences

// Title: Report Macros

// MACRO: `uvm_info

Of begin_event, end_event, transaction recording, and pipelined interfaces

$
0
0

What is the proper use of begin_tr() and end_tr() and their associated events?  There are these very nice descriptions for begin_event and end_event.

 

  // Variable: begin_event
  //
  // A <uvm_event> that is triggered when this transaction's actual execution on the
  // bus begins, typically as a result of a driver calling <uvm_component::begin_tr>.

  // Processes that wait on this event will block until the transaction has
  // begun.
  //
  // For more information, see the general discussion for <uvm_transaction>.
  // See <uvm_event> for details on the event API.
  //
  uvm_event begin_event;

 

  // Variable: end_event
  //
  // A <uvm_event> that is triggered when this transaction's actual execution on
  // the bus ends, typically as a result of a driver calling <uvm_component::end_tr>.

  // Processes that wait on this event will block until the transaction has
  // ended.
  //
  // For more information, see the general discussion for <uvm_transaction>.
  // See <uvm_event> for details on the event API.
  //
  //| virtual task my_sequence::body();
  //|  ...
  //|  start_item(item);    \
  //|  item.randomize();     } `uvm_do(item)
  //|  finish_item(item);   /
  //|  // return from finish item does not always mean item is completed
  //|  item.end_event.wait_on();
  //|  ...
  //
  uvm_event end_event; 


Great! That is exactly what I want and would expect.  Then begin_tr has even more verbiage that reinforces that:


  // Function: begin_tr
  //
  // This function indicates that the transaction has been started and is not
  // the child of another transaction. Generally, a consumer component begins
  // execution of a transactions it receives.
  //
  // Typically a <uvm_driver> would call <uvm_component::begin_tr>, which
  // calls this method, before actual execution of a sequence item transaction.
  // Sequence items received by a driver are always a child of a parent sequence.
  // In this case, begin_tr obtains the parent handle and delegates to <begin_child_tr>.
  //
  // See <accept_tr> for more information on how the
  // begin-time might differ from when the transaction item was received.
  //
  // This function performs the following actions:
  //  blah blah good details here ...
  extern function integer begin_tr (time begin_time=0);

 

begin_child_tr() and end_tr() have similar verbiage.  Notice the lines I've highlighted.  Now let's go look at the sequence side of things.  According the the UVM user's guide, the basic execution flow of a transaction in a sequence is as follows (this is also what the uvm_do macro implements):

  1. Call start_item() to create the item via the factory. 
  2. Optionally call pre_do() or some other functionality.
  3. Optionally randomize item.
d) Optionally call mid_do() or some other functionality, if desired.
  4. Call finish_item().
  5. Optionally call post_do() or some other functionality.
  6. Optionally call get_response(). 

However, start_item() has this bit of code in it. 


    `ifndef UVM_DISABLE_AUTO_ITEM_RECORDING
      void'(sequencer.begin_child_tr(item, m_tr_handle, item.get_root_sequence_name()));
    `endif

 

Which in turn calls uvm_component::begin_tr().  *Screeeeeeeching halt sound*  Whaaat?  The function description for begin_tr() just said it is "typically called by a driver".  But, it turns out that begin_tr() is in fact typically called by the sequence executing the transaction (indirectly via the sequencer).  Well, it turns out that this is documented, but the documentation has a bit of a multiple personality disorder.  Here's a snip from the uvm_transaction class documentation:


//------------------------------------------------------------------------------
//
// CLASS: uvm_transaction
//
// ... blah blah blah ...
//
// The intended use of this API is via a <uvm_driver> to call <uvm_component::accept_tr>,
// <uvm_component::begin_tr>, and <uvm_component::end_tr>
during the course of
// sequence item execution. These methods in the component base class will
// call into the corresponding methods in this class to set the corresponding
// timestamps (accept_time, begin_time, and end_tr), trigger the
// corresponding event (<begin_event> and <end_event>, and, if enabled,
// record the transaction contents to a vendor-specific transaction database.

 

I like how the intended use model (as previously stated) was reiterated here.  Which is then followed by this single line, which finally gets around to stating how this thing actually works.


// Note that start_item/finish_item (or `uvm_do* macro) executed from a
// <uvm_sequence #(REQ,RSP)> will automatically trigger
// the begin_event and end_events via calls to begin_tr and end_tr.

 

Oh, so the default configuration of the UVM library is to not implement the intended methodology, and instead encourage bad behavior.  That's nice.  Now let's follow that up with this line trying to reiterate the intended use model again.


// While convenient, it is generally the responsibility of drivers to mark a
// transaction's progress during execution. 

 

Ok. got it. My drivers should trigger these events, not the sequences.  This has been repeatedly stated at least 4 times up to this point!  Surely it must be as simple as calling begin_tr/end_tr at the appropriate times in my driver and the start_item/finish_item methods will adapt accordingly, no? 


// To allow the driver to control
// sequence item timestamps, events, and recording, you must add
// +define+UVM_DISABLE_AUTO_ITEM_RECORDING when compiling the UVM package.

 

Oh, of course!.  Now that we've been repeatedly told what the intended use model is, we finally discover that to actually use it, we must set an obscurely named flag that seems to refer only to automatic transaction recording.  Gosh, why didn't I think of that first?


// Alternatively, users may use the transaction's event pool, <events>,
// to define custom events for the driver to trigger and the sequences to wait on. Any
// in-between events such as marking the begining of the address and data
// phases of transaction execution could be implemented via the
// <events> pool.

 

Alternatively? It seems to me, that given that it's the default configuration of the library, it is the primary method to do so. And it also happens to be the only method I've seen demonstrated in every EDA vendor and service provider training I've seen on the subject. It goes on to talk about exactly why you should implement things in the intended way.


// In pipelined protocols, the driver may release a sequence (return from
// finish_item() or it's `uvm_do macro) before the item has been completed.
// If the driver uses the begin_tr/end_tr API in uvm_component, the sequence can
// wait on the item's <end_event> to block until the item was fully executed,
// as in the following example.
//
//| task uvm_execute(item, ...);
//|     // can use the `uvm_do macros as well
//|     start_item(item);
//|     item.randomize();
//|     finish_item(item);
//|     item.end_event.wait_on();
//|     // get_response(rsp, item.get_transaction_id()); //if needed
//| endtask
//|
//

 

Yep.  That is indeed the problem I want to solve. If only UVM would get out of it's own way.  It looks like someone was tasked with adding automated transaction recording to UVM and they decided to hi-jack the begin_event and end_event in order to do so.  Except they discovered a lot of VIP (most VIP?) didn't bother to make the appropriate calls to begin_tr and end_tr.  So they said, "Why don't I make the calls for them!", and here we are.  Unfortunately it breaks using begin_event and end_event for anything except automatic transaction recording.

 

To build a "proper" agent, I'm supposed to call begin_tr and end_tr in my driver.  This means I have to use +define+UVM_DISABLE_AUTO_ITEM_RECORDING, and lose that feature.  On top of that, other VIP is not going to implement the calls to begin_tr and end_tr, because they are going to assume the sequence does it for them.  So if you were using those events with other VIP, your tests are now broke until that other VIP is updated.

 

Taking this VIP the other way doesn't work either.  Calling begin_tr/end_tr from your driver and using it in a testbench that doesn't have the +define will cause double triggering of the events.  Maybe that won't mess anything up, but it certainly could.

 

So I ask these questions:

▪   Do you have a pipelined interface in your design?

▪   Are you interested in when your transactions start and end?

▪   Do you utilize begin_event and end_event?

▪   If not, what do you do instead?

▪   Would you utilize begin_event and end_event if they worked properly?

▪   If the default behavior of the library was changed to not automatically trigger these events, would it break your existing tests?

▪   Does anyone use the automatic transaction recording?

 

I think this really needs to be fixed. It simply means creating a couple of events specifically for automatic transaction recording to use, rather than hijacking the begin/end events.  If the automatic recording could take advantage of the developer manually triggering the begin/end events for greater accuracy, that would be great.  But not doing so, would be no worse than we have now.

What ever you do, don't use ...

$
0
0

I just saw a presentation on UVM tips and it recommended to NOT use the uvm_field macros. Several companies have come out and said that these generate large, cumbersome methods that are hard to debug, and that you should write the methods yourself. IMHO, this seems like bad advice. Having written these methods for VMM, I find it error prone and a waste of time. Why spend 10-20 minutes creating these when the macros do it automatically? Once you waste an hour debugging the copy method when you leave out one variable, you stick with the macros. And how slow are these automatic methods? They never show up on the simulation profiler.

 

This reminds me of when I used to change the oil on my car, and then left a rag on the engine that caught fire and cost me $200 to replace the O2 sensor, and could have ended up much worse. How much was I saving?

 

It is your time that is the most valuable thing. Use the macros to save coding time and debug time. Spend your time on something creative like understanding Flits!

Multiple CPU interfaces can access the same register model

$
0
0

Hi,

 

Assuming my DUT has 2 external CPU interfaces that can access to the same Register Model.

How should I implement it in my UVM environment ?

 

I guess I need 2 adapters and 2 predictors. Do I need to set 2 maps ? one per sequencer ?

Is it possible to set 2 different sequencers to the same map ? or we have to set 2 maps and set_sequencer to each one of them ?

 

Thanks, Ofir

Controlling verbosity while using component override

$
0
0

Hi,

 

My question is about controlling the verbosity for one agent when I am using override for it. Let me give more details here. I have base env and base agent class. My environment extends this classes and creates env and agent. I have base test also. From top module  I override the env class. In my test which is extended from base_test If i have to control verbosity for one agent I can write set_report_verbosity methods. But now this case gives me compilation error. As my env is overriden run time but when I have to sent the verbosity for perticular agent I have to give hierarchy path.

 

In my base test I have handle of base env as env. my component base_env is overridden with x_env. x_env is having x_agent. I want to control the verbosity for x_agent for debug purpose. in my start of simulation phase if I write like "env.x_agent" it gives error which is very obivious. Is there any sollution how can i control the vebosity of agent in this case?

 

 

Thanks,

Akshay


Disable UVM_INFO printout by verbosity

$
0
0

Hello,

I have a library with the sequence which exploits `uvm_info to print messages. It uses UVM_MEDIUM verbosity and AXI4STREAM_SLAVE id. I would like to disable those messages, however I can't change code of the library. For this reason, I have tried to call  m_sequencer.set_report_severity_id_verbosity(UVM_INFO, "AXI4STREAM_SLAVE", UVM_HIGH). Please notice, the function is called for sequencer on which the sequence is spawned. The report configuration of the sequencer:

 

 

# report handler state dump
#
#
# +-----------------+
# |   Verbosities   |
# +-----------------+
#
# max verbosity level =         200
# *** verbosities by id
#
# *** verbosities by id and severity
# UVM_INFO:AXI4STREAM_SLAVE --> UVM_HIGH
#
# +-------------+
# |   actions   |
# +-------------+
#
# *** actions by severity
# UVM_INFO = DISPLAY
# UVM_WARNING = DISPLAY
# UVM_ERROR = DISPLAY COUNT
# UVM_FATAL = DISPLAY EXIT
#
# *** actions by id
#
# *** actions by id and severity
#
# +-------------+
# |    files    |
# +-------------+
#
# default file handle =           0
#
# *** files by severity
# UVM_INFO =           0
# UVM_WARNING =           0
# UVM_ERROR =           0
# UVM_FATAL =           0
#
# *** files by id
#
# *** files by id and severity
# report server state

 

 

The problem is that the message is still displayed. I debugged the issue and noticed that the problem is in uvm_sequence_item.svh (I use UVM-1.1d). In the uvm_report_enabled function, there is a part:

if (m_client.get_report_verbosity_level(severity, id) < verbosity ||
        m_client.get_report_action(severity,id) == uvm_action'(UVM_NO_ACTION))
      return 0;
    else
      return 1;

As one can see, even if the message will be rejected by get_report_verbosity_level, it will get the default action from get_report_action and be printed at the end. According to my understanding, it's not a behaviour described in the documentation (uvm_report_object):

If the verbosity level of a report is greater than the configured maximum verbosity level of its report object, it is ignored.  If a report passes the verbosity filter in effect, the report’s action is determined.

The decision whether the message is printed is based on the assigned action, not verbosity. Moreover, I don't see sense of verbosity usage in this case. I would be grateful, if somebody could clarify my concerns.

 

Of course, another workaround is to call: m_sequencer.set_report_severity_id_action(UVM_INFO, "AXI4STREAM_SLAVE", UVM_NO_ACTION) however, I don't understand, why I couldn't get the same behaviour modifying verbosity.

UVM 1.2 , run_phase deprecation, and pre-compiling uvm base class

$
0
0

Q1) Is there truth to the hearsay that the Technical Committee (UVM Working Group) will/might remove run_phase's twelve sub phases (pre_reset, reset, etc.)?  If so, when might we expect it?

 

Q2) When is UVM 1.2 expected?

 

Q3) I am just looking into precompiling the uvm base class for our testbenches.  (I suppose that I would need two versions, one with -linedebug and one w/o.)   Does anyone have any comments about pre-compiling the UVM base class as I now work thru an example?

uvm supports vera verification env

$
0
0

hello,

 

We have one project which is previously verified using vera.  Now we want to update and reuse this sub-env  with uvm. Does it make sense?

 

thanks

 

andy

Notify scoreboard about memory accesses

$
0
0

Hi,

 

I have a UVM reg model, with both registers and memories.

Some of them are for the DUT configuration, and some of them are “status” and are read many times during normal operation.

 

What is the correct way for a scoreboard to be aware of all these accesses?

 

My reg model uses a uvm_reg_predictor, and I originally wanted to use its analysis port.

Unfortunately, only the register accesses are reported. Memory accesses are not. I even looked in the UVM source code and looks like memories are not yet supported.

 

Should I convert the memories to pseudo-“registers”?

 

Thanks, Ofir

set_rights for uvm reg

$
0
0

is there a way to set_rights of uvm reg for a specific map  ? (like uvm_field) if no why not ?

an alternative would be:

 

reg.get_fields(field_q)
foreach(field_q[i])
   field_q[i].set_rights("RO")
 

 

but why not allow modification of reg access directly ?

Viewing all 283 articles
Browse latest View live