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

SPI-Register Adaptor

$
0
0

Does anyone have an example of an SPI Register Model Adapter?  I am aware of the example for AHB Adapter.


UVM Monitor Help!!!!

$
0
0

Hi all,

I have a SPI interface, it has three modes to transfer the data out on IO[0:7]. In SPI standard there is just IO[0] is used. QPI mode, it uses IO[3:0] and In OPI mode, the whole IO are used. When driver receives a req from sequencer, it drives that req to the interface depending on modes. The interface sometimes goes with SPI, sometimes QPI or OPI. And I want to monitor the tx data, but I dont't know how to setup the monitor to sample the data corresponding to the mode that the driver has used. Are there ways to make monitor works in the same mode with the driver?

Thank you!

how to write more than one register using read and write functions

$
0
0

Hi,

I am using uvm standard register model , register adapter (bus2reg & reg2bus) to send and receive transaction to ral model and DUT.
and it is working fine if i do single read and write.(means i perform the 32 bit read n write using reg.read(status,address,data)reg.write(status,address,data))

My challange is that i have to perform the more than 32 bit transaction which performs the read and write on multiple registers,
If there any way to use the same reg.read/write method to perform more than one register

Noob question about how to add configurability to a test.

$
0
0

Hello everyone,

 

I'm fairly new to the verification using UVM. I've watched a bunch of lectures about the UVM methodology from the MentorGraphics website, and implemented a simple UVM test for a simple FIFO I designed. Currently, this test has no configurability and that is the next step I'd like to take to get to know UVM better.

 

The FIFO is pretty simple, with 1 write and 1 read port, full and empty flags, and a reset. In my test all data and read/write flags are generated randomly, but I want to change that in order to be able to be me who says when to write, when to read and what to write.

 

 am not very familiar with the concept of inheritance but I get the idea. Because of that, I haven't got any class that is extended from any of my own classes.

 

My question is where should I get started to add some configurability to the test?

Should I make several configuration classes and have general sequence/monitor/agent classes that get a configuration and do what they are supposed to by having big classes that interpret those configurations

OR

Should I have several smaller sequence/monitor/agent classes, each one doing a different thing, and have a simple configuration object indicate to the test which sequence/monitor/agent classes to override/use

OR

somehow a mix of both

Any suggestions or resources about configurability are welcome!

I stink at writing test plans.

$
0
0

Every time I sit down to write down my test plan, I simply feel as though I'm regurgitating my design requirements.  I've been through the Mentor Coverage Cookbook a few times already;  It has a UART and a couple other things.  Does anyone know other good examples / explanations of test plans? 

Everybody writes one of these things... right?

 

My example "function":

Receive an ARP request; generate an ARP reply.  The destination IP of the ARP must match the DUT IP in order for DUT to generate reply.

 

What line item(s) would I write in my "test plan"?

 

ARP request received by DUT    Type: covergroup, cross                     

ARP reply sent by DUT               Type: covergroup, cross

 

This is where I get really wrapped around the axle.  I already know what I sit down to write the test, I am going to simply randomize an ARP packet, and bombard my DUT.  It will receive ARP Replies (which it should drop), ARP Request addressed to someone else (drop this as well), and occasionally a Request with the correct address (accept and reply).

 

I definitely want coverpoints on all the non-supported behavior as well, but I take it that's not supposed to be mentioned in the test plan anywhere?   The whole point of constrained random stimulus generation is to find the bugs you aren't looking for, and it must be paired with a coverage collector to tell you where your blind sheep has wandered.

phase jump to function phases

$
0
0

Hi.

  in UVM, It is legal to have phase jump to any function phases.  but it seems in below demonstration code it does not work as I expected.  I expected the flag build_agt2 = 1 after the phase.jump(build_phase).

 

    class mycomponent extends uvm_component;

      .......

     bit build_agt2;

     function void build_phase(uvm_phase phase); 

           `create_agt1();

           if ( build_agt2)  

              `create_ag2() ; or

              // `override_agt1_by_agt2();  

     endfunction

 

    task run_phase;     

             // change flag build_agt2 to 1;

   endtask

 

   function void phase_ready_to_end;

          // if the imp phase  is in shutdown_phase

          // then phase.jump to build_phase

 endfunction

 

 

  

          

        

           

cloning a register

$
0
0

Hello,

 

I am running a simulation on a DUT that has a register model.

what i wish to do is hold a copy of that register model so that at certain times during the simulation

i can compare a current value of a register to a former value of that register taken at a previous point in time.

i don't want to save only the data of the registers, but an array of registers that will hold a copy of the whole register object,

including all of it's fields and other attributes.

 

i tried to create an array of type uvm_reg                                             uvm_reg registers_copy[]

and then use clone to copy a register to that array                               $cast(registers_copy[i], registers[i].clone());

 

but i get an error:

UVM_FATAL /tools/snps/vcs/current/etc/uvm-1.1/reg/uvm_reg.svh(3102) @ 3520.6ns: reporter [RegModel] RegModel registers cannot be cloned

 

how can i create a copy of my register model at certain points in time?

 

Thanks for your help,

Assaf

Multiple +uvm_set_severity are ignored

$
0
0

Hi,

 

UVM supports changing UVM severity (Fatal/Error/…) to new desired one from command line using +uvm_set_severity:

 +uvm_set_severity=<comp> ,<id> ,<current severity> ,<new severity> --

 

I’ve tried it and it works fine with one setting (+uvm_set_severity)

However, I’ve tried to change severity of several paths/IDs (by specifying +uvm_set_severity several times) – and it didn’t work. Seems that only the 1st one is accepted and others are ignored)

Example:

+uvm_set_severity=uvm_test_top.producer_agent.monitor,ERR_TIMEOUT_ID1,UVM_ERROR,UVM_WARNING  +uvm_set_severity=uvm_test_top.consumer_agent.monitor,ERR_TIMEOUT_ID2,UVM_ERROR,UVM_WARNING

Is it UVM known limitation or a bug ?

 

BTW, using widcard (*) indeed works well, but I wish to have better controlability (set severity of 2 different IDs in 2 different <comp>/path)

 

Regards, Ofir

 

 

Relevant code in uvm_component.svh :

function void uvm_component::m_set_cl_sev;
  // _ALL_ can be used for ids or severities
  //  +uvm_set_severity=<comp>,<id>,<orig_severity>,<new_severity>
  //  +uvm_set_severity=uvm_test_top.env0.*,BAD_CRC,UVM_ERROR,UVM_WARNING

  static string values[$];
  static bit first = 1;
  string args[$];
  uvm_severity orig_sev, sev;

  if(!values.size())
    void'(uvm_cmdline_proc.get_arg_values("+uvm_set_severity=",values));
 

Am I done testing yet? A (fun!) coverage question..

$
0
0

I want to verify the following behavior:

"DUT shall only accept command A, and reject all others while in the Powerup state.  While not in Powerup, accept all commands"

This is the state of the DUT following a reset.

 

Option 1 - No covergroup

After a reset, send all commands that are NOT A, followed by command A.  If the scoreboard doesn't fail, then I'm good to go.

 

Option 2 - Covergroup

Have a monitor hanging off an agent that, when it detects a command is written, it crossed the state of the DUT with the command being written.

 

With option 1, I have no coverage metric that the test was even performed.  However, I can very quickly write a test, and it doesn't require any components.  The integrity of the test is paramount here.

With option 2, I've got to use a bound virtual interface to access the state bits of the DUT, and also build a coverage collector.

 

-------------------------------------------------------------------------------------------------------------------

My heart wants to simply define my coverage model entirely via covergroups, and then generate stimuli until I meet 100%.

My brain, however, says no, no...  don't verify that you sent the sequence Cmd A -> Cmd C -> Cmd E -> Cmd A, just write a directed test that does that.

 

Thoughts?

UVM Monitor help!!!

$
0
0

Hi all,

I have a SPI interface, it has three modes to transfer the data out on IO[0:7]. In SPI standard there is just IO[0] is used. QPI mode, it uses IO[3:0] and In OPI mode, the whole IO are used. When driver receives a req from sequencer, it drives that req to the interface depending on modes. The interface sometimes goes with SPI, sometimes QPI or OPI. And I want to monitor the tx data, but I dont't know how to setup the monitor to sample the data corresponding to the mode that the driver has used. Are there ways to make monitor works in the same mode with the driver?

Thank you!

How to set verbosity for uvm_object (not component)?

$
0
0

Is there a command-line command to change the verbosity for a uvm_object (like a configuration object)?

 

For components, I use:

+uvm_set_verbosity=test_top.env.myagent.*,_ALL_,UVM_DEBUG,run

 

I want to leave the entire testbench verbosity as sv_medium, except for one object of the following class.  Not being a component, it's not in the component hierarchy.

class plb_agent_configuration extends agent_cfg_base #(plb_transaction);
  `uvm_object_utils( plb_agent_configuration )

  virtual interface plb_driver_bfm   driver_bus;
  virtual interface plb_monitor_bfm  monitor_bus;

  function new( string name = "" );
    super.new( name );
  endfunction

  virtual task access(inout TRANS_T txn);
    driver_bus.access(txn);
  endtask

  virtual task monitor(inout TRANS_T txn);
    monitor_bus.monitor(txn);
  endtask

  virtual task wait_clk(input uint32_t num);
    monitor_bus.wait_for_clk(num);
  endtask

  virtual task wait_rsp();
    while (monitor_bus.cb.RspFlag_i!=1) @monitor_bus.cb;
    `uvm_info(report_id, "response!", UVM_DEBUG)
  endtask

endclass

controlled transition from one phase to another

$
0
0

Hi,

 

As per my understanding, connect_phase does not start until all build_phase do not complete.

 

How is this mechanism controlled?

 

I did not find anything in uvm reference manual about this.

Please let me know if there is any.

 

Thanks.

extracting data from uvm_do_with macro

$
0
0

Hello,

 

let's say i have a sequence, in this sequence i'm reading data using the uvm_do_with macro.

an example would be a read transaction in an APB agent.

 

how do i extract the data from it?

 

PARTIAL CODE:

 

    virtual task  body();
        apb_item#(AW, DW) it;
 
        case(op_kind)
            `APB_READ: begin
                `uvm_do_with(it,
                    {
                    it.address == tr_address;
                    it.rw          == op_kind;
                    }
                );// `uvm_do_with
            end
 
        endcase
 
    endtask: body
 
Thx,
Assaf
 

UVM Sequence Help

$
0
0

Hi all,

 

I am experiencing a problem with sequence/sequencer. I think that the problem is inside the sequence

class Sequence0 extends uvm_sequence #(Packet);

  function new(string name = "Sequence0");
		super.new(name);
		`uvm_info(get_full_name(), "Sequence new()",UVM_LOW);
	endfunction : new

	Packet item;
   
	 	
  `uvm_sequence_utils(Sequence0, Sequencer) 
        
	
	virtual task body();
    forever begin
		    `uvm_info(get_full_name(), "Sequence build()",UVM_LOW);           
			`uvm_do_with(item,{da.size == 6;}); 
                     
  	end
	endtask : body
	
endclass : Sequence0

The compilation works; on the other side the run phase shows a

 

"UVM_FATAL ./sequence_macsec_tx.sv(11) @ 0: uvm_test_top.t_env.Seqncr@@Sequence0 [DCLPSQ] \$unit ::\Sequence0::m_set_p_sequencer  uvm_test_top.t_env.Seqncr.Sequence0 Error casting p_sequencer, please verify that this sequence/sequence item is intended to execute on this type of sequencer"

 

I inserted on purpose the `uvm_info and the last message that I get is Sequence new() as stated in line 5. 

 

Do you have any idea about the above error? 

 

Thanks in advance 

 

 

uvm_builtin_reg_test_seq & default sequences

$
0
0
I am trying to run the uvm builtin register sequences.   I seem to have broken our usage of them in porting code from a previous project.
 
Q1:  In the past, we've started them as default sequences.  Is there any way to have an error/warning appear if a 'set', such as the below, is never utilized (or 'get'-ed)? 
uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_reg_agent.m_seq_reg.main_phase", "default_sequence", uvm_builtin_reg_test_seq::type_id::get());
I've added
uvm_top.print_topology();
and
uvm_config_db::dump();
and it seems the ::set should be working, but nothing is starting.
 
Q2:  Are builtin (base class) sequences automatically "::created" somehow/somewhere?   (Creation/new-ing is still necessary when you setup a default sequence, right?  Or is there some magic singleton-ness that happens?)
 
Q3: My error of the moment is as follows.  Your thoughts are appreciated.
UVM_FATAL @ 39990: reporter@@seq [SEQ] neither the item's sequencer nor dedicated sequencer has been supplied to start item in seq
always@(posedge clk),
ljepson74

uvm_mem_mam request/reserve region size

$
0
0

Is there some good reason that the n_bytes argument to uvm_mem_mam request_region() and reserve_region() are unsigned ints and not unsigned longints?

 

It seems inconsistent with the address "offset" arguments/attributes which *are* longints (or bit [63:0]) and obviously it prevents allocation of regions larger than 2**32-1.

 

Perhaps this could/should be fixed in a future release?

 

Or is there some subtlety I'm missing.

 

Thanks.

 

Walker

 

Different flow for uvm_recorder usage in uvm_component between UVM1.1 and UVM1.2

$
0
0

Hi, All:

 

I noticed that there are some differences in the usage for uvm_recorder between UVM1.1 and UVM1.2.  That made me a little confusion when trying the transaction recorder for verdi.  Here is some example code for m_begin_tr task inside the uvm_component.

 

 

For UVM 1.1:

 

kind = (has_parent == 0) ? "Begin_No_Parent, Link" : "Begin_End, Link";
 
    // Modified by Verdi
`ifdef UVM_VCS_RECORD
    desc = {desc,
            $psprintf("Object ID: %0s (@%0d)\n", $vcs_get_object_id(tr), tr.get_inst_id()),
            $psprintf("Sequencer ID: %0s (@%0d)\n",  $vcs_get_object_id(this), get_inst_id())};
 
    if ($cast(seq_base,tr)) begin
      desc = {desc,
              "Phase: ", seq_base.starting_phase ? seq_base.starting_phase.get_name() : "N/A", "\n"};
      if(seq_base.get_parent_sequence()!=null) begin
         desc = {desc,
                 $psprintf("Parent Sequence ID: %0d\n",  seq_base.get_parent_sequence().get_inst_id())};
      end
    end else if($cast(seq_item, tr)) begin
      if(seq_item.get_parent_sequence()!=null) begin
         desc = {desc,
                 $psprintf("Parent Sequence ID: %0d\n",  seq_item.get_parent_sequence().get_inst_id())};
      end
    end
`endif
    // End
 
    tr_h = recordr.begin_tr(kind, stream_h, name, label, desc, begin_time);
 
    if (has_parent && parent_handle != 0)
        recordr.link_tr(parent_handle, tr_h, "child");
 
    m_tr_h[tr] = tr_h;
 
    if (recordr.check_handle_kind("Transaction", link_tr_h) == 1)
      recordr.link_tr(tr_h,link_tr_h);
 
    do_begin_tr(tr,stream_name,tr_h);
 
 
For UVM 1.2:
 
if (uvm_verbosity'(recording_detail) != UVM_NONE) begin
      if ((stream_name == "") || (stream_name == "main")) begin
        if (m_main_stream == null)
           m_main_stream = db.open_stream("main", this.get_full_name(), "TVM");
         stream = m_main_stream;
      end
      else
        stream = get_tr_stream(stream_name);
 
      if (stream != null ) begin
         kind = (parent_recorder == null) ? "Begin_No_Parent, Link" : "Begin_End, Link";
 
         recorder = stream.open_recorder(name, begin_time, kind);
 
         if (recorder != null) begin
            if (label != "")
              recorder.record_string("label", label);
            if (desc != "")
              recorder.record_string("desc", desc);
 
            if (parent_recorder != null) begin
               tr_database.establish_link(uvm_parent_child_link::get_link(parent_recorder,
                                                                          recorder));
            end
 
            if (link_recorder != null) begin
               tr_database.establish_link(uvm_related_link::get_link(recorder,
                                                                     link_recorder));
            end
            m_tr_h[tr] = recorder;
         end
      end
 
      handle = (recorder == null) ? 0 : recorder.get_handle();
      do_begin_tr(tr, stream_name, handle);
 
   end
 
 
Please note, in UVM 1.1, it directly call the begin_tr of the recorder without any other behavior.  In UVM 1.2, it will open the recorder by calling the stream.open_recorder.  And in the open_recorder of stream, it will call the 'm_do_open' task from recorder.  Here comes the problem, in m_do_open of recorder, it will check if the recorder has been opened more than onece like below.  So if we have many sequencers running parallely,  we can not guarantee the recorder is managed(open->free->open->free) in order.  It will cause the recorder be opened many times and trigger the ERROR.
 
function void m_do_open(uvm_tr_stream stream, time open_time, string type_name);
     uvm_tr_stream m_stream;
     if (stream == null) begin
        `uvm_error("UVM/REC/NULL_STREAM",
                   $sformatf("Illegal attempt to set STREAM for '%s' to '<null>'",
                             this.get_name()))
        return;
     end
 
     if (-_stream_dap.try_get(m_stream)) begin
        `uvm_error("UVM/REC/RE_INIT",
                   $sformatf("Illegal attempt to re-initialize '%s'",
                             this.get_name()))
        return;
     end
 
     m_stream_dap.set(stream);
     m_open_time = open_time;
     m_is_opened = 1;
 
     do_open(stream, open_time, type_name);
  endfunction : m_do_open
 

Does anyone konw about this?  Maybe I misunderstand the usage.  Can anyone help to explain this?  Thanks!

using uvm_config_db::get inside a module

$
0
0

Hi,

 

can i use uvm_config_db::get function from inside a module?

i want to create a configuration object in the test, set it at the config_db and get it in a VIP written as a module.

something like this:

 

module vip();

initial begin
    // Wait for first clock - this means we are in the main phase
    @(posedge if.clk);
 
    if (!uvm_config_db#(vip_config)::get(null, "uvm_test_top","cfg", cfg)) begin
        `uvm_fatal("CFGERR", "%m vip cfg not set")
    end
    ...
end
endmodule
 
i tried this and got the fatal error, meaning the cfg wasn't found.
 
i tried instead to create a typedef struct and pass it from the test to the module using set and get but the simulation crashed - "--- Stack trace follows".
 
Any help would be much appreciated.
 
Thx,
Assaf

uvm sequence for slave implementation

$
0
0

Hello,

 

I'm trying to implement an AXI Slave VIP and have few questions regarding the implementation.

In this case, the DUT is the master. The AXI Slave checks the interface for valid read /write signals and performs a read/write operation from a memory model. It returns back the write response/read data back to the DUT.

 

1. Since this is a slave VIP , do I need a slave sequence which runs forever sending transactions to the driver ? This is similar to the UVM example where the monitor and sequencer are connected by an analysis port and the sequence calls the peek function to check if a valid transaction is available from the monitor. 

 

(OR)

 

2. Can I skip the sequence/sequencer part and just connect my monitor and driver using an analysis port and pass on the observed transaction from the monitor to the driver for further action ?

 

(OR)

 

3. Im thinking of a 3rd alternative of just using the monitor to the observe the interface and drive back the write response/ read data back using the monitor itself and leave the driver empty. 

 

Please let me know your valuable thoughts and suggestions.

 

Thanks,

Madhu 

How to file a bug?

Viewing all 283 articles
Browse latest View live