Scoreboard gets empty items from the monitor

I am interested in learning UVM, so I have downloaded one of the uvm examples (spi).
I have made some modifications to the UVM testbench since the SPI RTL that I have has different functionality.
I could see that that my sequence items are generated as I expect. Next to that my driver and monitor are also doing what they should do. also the functional coverage block. The problem that I have is with the scoreboard. The monitor is broadcasting the transactions (via write method) to both functional coverage block (uvm subscriber) and to the scoreboard, I see that transactions are correctly broadcasted to the subscriber (functional coverage block) but not to the scoreboard. This the code of my scoreboard:

class spi_scoreboard extends uvm_scoreboard;

`uvm_component_utils(spi_scoreboard)
uvm_tlm_analysis_fifo #(spi_seq_item) spi_fifo;
spi_seq_item item;

function new(string name = “”, uvm_component parent = null);
super.new(name, parent);
endfunction

function void build_phase(uvm_phase phase);
spi_fifo = new(“spi_fifo”, this);
endfunction: build_phase

task run_phase(uvm_phase phase);
forever
begin
spi_fifo.get(item);
if(item.pedge_mosi.size ==0)
uvm_info("SPI_SB_REPORT:", $sformatf("Item is empty !!!!"), UVM_LOW) else uvm_info(“SPI_SB_REPORT:”, $sformatf(“Item is %p”,item), UVM_LOW)
end
endtask: run_phase

The get method (spi_fifo.get(item);) is getting something because it gets executed the exact same number of transactions that being broadcasted. But the items are empty (item.pedge_mosi.size is always 0, this is also the case for all other the item object attributes), so I am not getting how these items reach the subscriber correctly but not the scoreboard. I am suspecting that something is wrong with connection from Monitor to Scoreboard, but have no clue.

This is how the TLM connection of the monitor to the scoreboard is done:

function void spi_env::connect_phase(uvm_phase phase);

// Connect monitor to subscriber
m_spi_agent.ap.connect(m_func_cov_monitor.analysis_export);

// Connect monitor to scoreboard
m_spi_agent.ap.connect(m_scoreboard.spi_fifo.analysis_export);


endfunction: connect_phase

Any clue why I don’t get the items?
all what I get get is:

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(63) @ 1342110: uvm_test_top.m_env.m_scoreboard [SPI_SB_REPORT:] Item is empty !!!

This message gets repeated as many times as the number of the broadcasted transactions.

In reply to adnanesbai:

Do you have a print from monitor just before write() or from subscriber to debug further?

Srini
http://verifnews.org/jdi/

I have added a print just before the write() in the monitor, and also in the other components (driver,scoreboard,functional coverage), this is what I get (10 transactions):

UVM_INFO @ 0: reporter [RNTST] Running test spi_interrupt_test…

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #1

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] a2 c4 7b 87 95 24 86 b6 25 c7 49

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 186100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] a2 c4 7b 87 95 24 86 b6 25 c7 49

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 186100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] a2 c4 7b 87 95 24 86 b6 25 c7 49

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 186100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 196100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #2

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 196100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 10 d8 8d 71 63

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 286100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 10 d8 8d 71 63

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 286100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 10 d8 8d 71 63

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 286100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 296100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #3

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 296100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 62 74 13 da 88 11 a3 de 4d 92

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 466100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 62 74 13 da 88 11 a3 de 4d 92

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 466100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 62 74 13 da 88 11 a3 de 4d 92

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 466100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 476100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #4

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 476100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 2 1c 2d 70 22

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 566100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 2 1c 2d 70 22

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 566100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 2 1c 2d 70 22

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 566100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 576100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #5

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 576100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 21 2c 6d f0 32

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 666100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 21 2c 6d f0 32

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 666100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 21 2c 6d f0 32

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 666100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 676100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #6

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 676100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 51 84 73 7a 64

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 766100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 51 84 73 7a 64

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 766100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 51 84 73 7a 64

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 766100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 776100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #7

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 776100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 63 20 20 9 3 5a d4 b5 33

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 930100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 63 20 20 9 3 5a d4 b5 33

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 930100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 63 20 20 9 3 5a d4 b5 33

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 930100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 940100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #8

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 940100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 12 96 1a f3 55 e4 a

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 1062100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 12 96 1a f3 55 e4 a

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 1062100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 12 96 1a f3 55 e4 a

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 1062100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 1072100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #9

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 1072100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 1 7 9a

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 1130100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 1 7 9a

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 1130100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 1 7 9a

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 1130100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO …/TESTBENCH/sequences/spi_sequence_lib_pkg.sv(24) @ 1140100: uvm_test_top.m_env.m_spi_agent.m_sequencer@@spi_transfer [TRANSACTION] #10

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_driver.svh(43) @ 1140100: uvm_test_top.m_env.m_spi_agent.m_driver [SPI_DRIVER] 11 e 4c c1

UVM_INFO …/TESTBENCH/agents/spi_agent/spi_monitor.svh(108) @ 1214100: uvm_test_top.m_env.m_spi_agent.m_monitor [SPI_MONITOR] 11 e 4c c1

UVM_INFO …/TESTBENCH/env/spi_functional_coverage.svh(90) @ 1214100: uvm_test_top.m_env.m_func_cov_monitor [SPI_FUNC_COV] 11 e 4c c1

UVM_INFO …/TESTBENCH/env/spi_scoreboard.svh(65) @ 1214100: uvm_test_top.m_env.m_scoreboard [SPI_SCOREBOARD:] '{} the queue item.pedge_mosi[$] is empty!!!

UVM_INFO verilog_src/uvm-1.0p1/src/base/uvm_objection.svh(1116) @ 1224100: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase

the data is the same in the driver, the monitor and the functional coverage, but empty in the scoreboard.

Adnane

In reply to adnanesbai:

Which example is it? Is it the tb_build?
I’m wondering where the queue comes from?

In reply to adnanesbai:

In your FCOV subscriber by any chance are you modifying the item received? Since elements are passed by reference this could be the case. Show us the code on subscriber side.

Srini

Yes indeed it’s the tb_build + updates, I have made some updates to adapt it to my RTL, for instance the tb_build spi_seq_item has been updated to have the following members:

logic [7:0] nedge_mosi[]; logic [7:0] pedge_mosi[];
logic [7:0] nedge_miso[]; logic [7:0] pedge_miso[];

instead of the ones in the original example:

logic [127:0] nedge_mosi;
logic [127:0] pedge_mosi;
logic [127:0] nedge_miso;
logic [127:0] pedge_miso;

This the code of the subscriber:

class spi_functional_coverage extends uvm_subscriber #(spi_seq_item);

`uvm_component_utils(spi_functional_coverage)

typedef enum bit [1:0] {A8=0,A16=1,A24=2,A0=3} addr_size_t;
typedef enum bit [1:0] {D8=0,D16=1,D32=2} data_size_t;
typedef enum bit {RD=0,WR=1} access_t;
typedef enum bit [2:0] {B1=0,B2=1,B4=2,B8=3,B16=4,B32=5,B64=6,UNDEF=7} burst_t;

addr_size_t address;
data_size_t data;
access_t wnr;

covergroup spi_cmd_cov;
ADDR: coverpoint address {
bins A8 = {A8};
bins A16 = {A16};
bins A24 = {A24};
}
DATA: coverpoint data {
bins D8 = {D8};
bins D16 = {D16};
bins D32 = {D32};
}
TYP: coverpoint wnr {
bins RD = {RD};
bins WR = {WR};
}
COV_CROSS: cross DATA, ADDR, TYP;
endgroup: spi_cmd_cov

extern function new(string name = “spi_functional_coverage”, uvm_component parent = null);
extern function void write(T t);

endclass: spi_functional_coverage

function spi_functional_coverage::new(string name = “spi_functional_coverage”, uvm_component parent = null);
super.new(name, parent);
spi_cmd_cov = new();
endfunction

function void spi_functional_coverage::write(T t);
string S;
foreach(t.pedge_mosi[j])
S = {S,$sformatf(" %0h",t.pedge_mosi[j])};
`uvm_info(“SPI_FUNC_COV”,S, UVM_LOW)
$cast(address,t.pedge_mosi[0][7:6]);
$cast(data,t.pedge_mosi[0][5:4]);
$cast(wnr,t.pedge_mosi[0][0]);
spi_cmd_cov.sample();
endfunction: write

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

This is the monitor:

class spi_monitor extends uvm_component;

// UVM Factory Registration Macro
//
`uvm_component_utils(spi_monitor);

// Virtual Interface
virtual spi_if SPI;

//------------------------------------------
// Data Members
//------------------------------------------

//------------------------------------------
// Component Members
//------------------------------------------
uvm_analysis_port #(spi_seq_item) ap;

//------------------------------------------
// Methods
//------------------------------------------

// Standard UVM Methods:

extern function new(string name = “spi_monitor”, uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern task run_phase(uvm_phase phase);
extern function void report_phase(uvm_phase phase);

endclass: spi_monitor

function spi_monitor::new(string name = “spi_monitor”, uvm_component parent = null);
super.new(name, parent);
endfunction

function void spi_monitor::build_phase(uvm_phase phase);
ap = new(“ap”, this);
endfunction: build_phase

task spi_monitor::run_phase(uvm_phase phase);
spi_seq_item item;
logic [7:0] pedge_mosi_int;
logic [7:0] pedge_miso_int;
string S;

item = spi_seq_item::type_id::create(“item”);

while(SPI.CSN === 1’bx) begin
#1ns;
end

forever begin

item.p = 0;
item.pedge_mosi = '{};
item.pedge_miso = '{};
S = "";
fork
  begin
    @(negedge SPI.CSN);
    forever
    begin
      pedge_mosi_int=0;
      pedge_miso_int=0;
      for(int i=7; i>=0; i--)
      begin
        @(posedge SPI.SCLK);
          pedge_mosi_int[i] = SPI.MOSI;
          pedge_miso_int[i] = SPI.MISO;
          item.p++;
      end
      item.pedge_mosi.push_back(pedge_mosi_int);
      item.pedge_miso.push_back(pedge_miso_int);
    end
  end
  begin
    @(posedge SPI.CSN);
  end
join_any
disable fork;
foreach(item.pedge_mosi[j])
  S = {S,$sformatf(" %0h",item.pedge_mosi[j])};
`uvm_info("SPI_MONITOR",S, UVM_LOW)
ap.write(item);

end
endtask: run_phase

Please note that this is not a complete example, I was just playing with this example and I got stuck with the issue that I have described.

Siri,

I want to add that the issue (scoreboard tlm fifo items are empty) was there even before adding the FCOV subscriber, I have recently added the subscriber just to narrow the debugging, more exactly to know if the problem is in the producer (monitor) or the consumer (scoreboard). since the FCOV is able to get all the transactions, it looks to me that the monitor is okay and something is wrong with the scoreboard.

Regards,

Adnane

In reply to adnanesbai:

You need to clone your item in the monitor before sending it out the analysis port. Since you don’t do this, you reuse the same ‘item’ handle, which is immediately zeroed out after you call write(), which is why you see an empty item.

In reply to adnanesbai:

Adnane,
Indeed it is the “ref” issue that is causing this. You should do the item = item_type::type_id::create() inside your forever loop.

BTW - please use tags to format your code in these posts, makes it easier to read, follow.

Regards
Srini

In reply to cgales:

Yes, you have identified the issue, without cloning, the items get emptied right after the write() call. In fact the reason why I have commented out the line where the items get cloned, is because I have seen that the cloned items are always empty, while the items themselves are not (after the cloning), so I have decided to use the items themselves. But after debugging I found out why cloning does not work, it is because I have the do_copy() function commented out, I thought that obj.clone() does not use this function, but it does. Now my items are observed in the scoreboard and it has nothing to do with the uvm_tlm_analysis_fifo TLM connection (which I was suspecting in the beginning).

Thanks

In reply to DESIGN_DV_TOPICS:
if you could create item in forever loop, just like this:
forever begin
item = spi_seq_item::type_id::create(“item”);

ap.write(item);
end


In reply to Allan_mo:

Thank you for your feedback, the code is working fine without creating the items inside the forever loop, cloning the items before broadcasting them has fixed the issue. So now I am able to correctly receive the items in the scoreboard and also in the functional coverage block. But I agree that creating the objects inside the forever loop is also a solution.

Thanks