Last pushback in queue in scoreboard write method, overriding all values in queue

I have a monitor and a scoreboard connected through uvm_analysis_port/imp. I am sampling some values in the monitor and using the write function to transport those to the scoreboard. The scoreboard is also getting those values as reflected in the info statement and putting it in a queue. However, when I am reading the queue in check_phase, all the entries in the queue have the same value equal to the last value written in the queue. please help debug.


class my_scoreboard extends uvm_scoreboard;
  `uvm_component_utils(my_scoreboard)
  
  my_sequence_item tr_q[$];
  my_sequence_item tr1;
  
  logic [7:0] prev_a;
  logic [7:0] prev_b;
  
  uvm_analysis_imp#(my_sequence_item, my_scoreboard) ai;
  
  
  function new(string name="scoreboard",uvm_component parent);
    super.new(name,parent);
    ai=new(name,this);
  endfunction
  
  function void write(my_sequence_item tr_c);
    `uvm_info("",$sformatf("writing to queue a-%d, b-%d",tr_c.a,tr_c.b),UVM_LOW); //printing correct values
    tr_q.push_back(tr_c);
  endfunction
  
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    //write match logic here
    phase.drop_objection(this);
  endtask
  
  function void check_phase(uvm_phase phase);
    super.check_phase(phase);
    tr1 = my_sequence_item::type_id::create("tr1");
    foreach(tr_q[i]) $display(tr_q[i].a); //printing all same values, unintended
    while(tr_q.size()) begin
      $display("tr_q.size-%d",tr_q.size); //prints correct queue size
      tr1=tr_q.pop_front();
      if(tr1.doAdd) begin
        if(!(tr1.result===(prev_a+prev_b)))
          `uvm_info("",$sformatf("add result-%d,a-%d,b-%d",tr1.result,prev_a,prev_b), UVM_LOW);
      end
      else begin
        if(!(tr1.result===(prev_a-prev_b)))
          `uvm_info("",$sformatf("sub result-%d,a-%d,b-%d",tr1.result,prev_a,prev_b), UVM_LOW);
      end
      prev_a=tr1.a;
      prev_b=tr1.b;
    end
  endfunction
endclass


class my_monitor extends uvm_monitor;
  `uvm_component_utils(my_monitor)
  my_sequence_item tr_m;
  virtual add_sub_if vif;
  uvm_analysis_port#(my_sequence_item) ap;
  
  function new(string name,uvm_component parent);
    super.new(name,parent);
    ap=new(name,this);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    //if(!uvm_config_db#(virtual add_sub_if)::get(this,"","add_sub_if",vif))
    //   `uvm_error("","Error in Monitor");
  endfunction
  
  task run_phase(uvm_phase phase);
    tr_m=my_sequence_item::type_id::create("tr_m");
    forever begin
      @(vif.cb);
      tr_m.a=vif.a;
      tr_m.b=vif.b;
      tr_m.doAdd=vif.doAdd;
      tr_m.result=vif.cb.result;
      ap.write(tr_m);
      `uvm_info(get_name(),$sformatf("a-%d, b-%d, doAdd-%d, result-%d",tr_m.a,tr_m.b,tr_m.doAdd,tr_m.result),UVM_LOW);
    end
  endtask
  
endclass

class my_agent extends uvm_agent;
  `uvm_component_utils(my_agent);
  
  my_driver drv;
  my_sequencer sqr;
  my_monitor mon;
  my_scoreboard scbd;
  
  virtual add_sub_if vif;
  
  function new(string name="agent", uvm_component parent);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    //build driver, monitor, scoreboard here
    super.build_phase(phase);
    drv=my_driver::type_id::create("drv",this);
    sqr=my_sequencer::type_id::create("sqr",this);
    mon=my_monitor::type_id::create("mon",this);
    scbd=my_scoreboard::type_id::create("scbd",this);
    if(!uvm_config_db#(virtual add_sub_if)::get(this,"","add_sub_if",vif))
      `uvm_error(get_name(),"Error getting vif")
  endfunction
  
  function void connect_phase(uvm_phase phase);
    //connect driver, sequencer here
    drv.seq_item_port.connect(sqr.seq_item_export);
    mon.ap.connect(scbd.ai);
    drv.vif=this.vif;
    mon.vif=this.vif;
  endfunction
  
endclass: my_agent



Please reply if you need the complete code to help debug.

In reply to possible:

In the run_phase of your monitor, move the creation of tr_m inside the forever loop. Every write() needs a different object.

In reply to possible:

I have a monitor and a scoreboard connected through uvm_analysis_port/imp. I am sampling some values in the monitor and using the write function to transport those to the scoreboard. The scoreboard is also getting those values as reflected in the info statement and putting it in a queue. However, when I am reading the queue in check_phase, all the entries in the queue have the same value equal to the last value written in the queue. please help debug.
Please reply if you need the complete code to help debug.

Additionally what Dave is saying you are wasting your computer resources using a queue instead of an uvm_analysis_fifo and doing the compares after the run_phase instead of doing them on the fly.
Assume you have only 100 seq_items with maybe 10 data members this needs a lot of memory space. When using the fifo and checking on the fly you do not need so much spce. This will result in a faster simulation run.

In reply to chr_sue:

Thanks for the recommendation!